【问题标题】:HttpContext is null after adding MessageHandler添加 MessageHandler 后 HttpContext 为空
【发布时间】:2015-12-22 02:15:45
【问题描述】:

我正在开发一个 WebAPI,并且一直在接收我的 POST 数据,如下所示:

[HttpPost]
        public Int16 Foo()
        {
            var input = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
            Model_Deserialized model = JsonConvert.DeserializeObject<Model_Deserialized>(input);
            ...
        }

最近我觉得有必要记录所有发送过来的请求。我正在尝试使用http://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi 建议的方法,但按照这些步骤操作后,我的输入变量开始为空字符串。

这就是我的消息处理程序的样子

public abstract class MessageHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var corrId = string.Format("{0}{1}", DateTime.Now.Ticks, Thread.CurrentThread.ManagedThreadId);
            var requestInfo = string.Format("{0} {1}", request.Method, request.RequestUri);

            var requestMessage = await request.Content.ReadAsByteArrayAsync();

            String ip;

            if (request.Properties.ContainsKey("MS_HttpContext"))
            {
                var ctx = request.Properties["MS_HttpContext"] as HttpContextWrapper;
                if (ctx != null)
                {
                    ip = ctx.Request.UserHostAddress;
                }
            }

            else
            {
                 ip = "error";
            }

            await IncommingMessageAsync(corrId, requestInfo, requestMessage, ip);

            var response = await base.SendAsync(request, cancellationToken);

            return response;
        }


        protected abstract Task IncommingMessageAsync(string correlationId, string requestInfo, byte[] message, String ip);
    }

这是我的 MessageLoggingHandler

public class MessageLoggingHandler : MessageHandler
    {
        protected override async Task IncommingMessageAsync(string correlationId, string requestInfo, byte[] message, String ip)
        {
            await Task.Run(() =>
                WriteToFile(ip + "{" + correlationId + "} - Request: {" + requestInfo + "}\r\n{" + Encoding.UTF8.GetString(message) + "}"));
        }


        private void WriteToFile(string text)
        {
            string path = "C:\\Logs\\ServiceLog" + DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + ".txt";
            using (StreamWriter writer = new StreamWriter(path, true))
            {
                writer.WriteLine(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt") + "--" + text);
                writer.Close();
            }
        }
    }

我也将此添加到我的 Global.asax

GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageLoggingHandler());

在我的 web.config 中我已经尝试添加

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<compilation debug="true" targetFramework="4.5">

有没有办法坚持使用这种方法,而不是创建一个日志记录例程并从每个函数中调用它?

【问题讨论】:

    标签: c# post asp.net-web-api controller httpcontext


    【解决方案1】:

    要明确HttpContext 不能为空 - 它是静态的。 HttpContext.Current 是空的吗?或者我的猜测是HttpContext.Current.Request.InputStream 为空。 Web api 自动读取流并处理它并将帖子正文反序列化为您的操作输入。因此,您应该将您的 Web Api 操作编码为如下所示:

    [HttpPost]
    public Int16 Foo(Model_Deserialized model)
    {
    
        ...
    }
    

    【讨论】:

    • 只是添加 - Web Api 抽象出大多数序列化/反序列化情况,因此在大多数情况下您不应该进行手动反序列化。
    • 此 WebAPI 用于移动应用程序。以前在app里序列化数据,在api中反序列化,是不是应该直接把数据作为模型发送?
    • 另外...这是否意味着如果我的 MessageHandler 在我的控制器之前读取 InputStream,它只会处理内容?直接反序列化的方法能解决这个问题吗?
    • 利用InputStream只能读取一次的信息,我把控制器改成了HttpContext.Current.Request.InputStream.Position = 0;并让它工作
    猜你喜欢
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2018-05-04
    • 2017-11-04
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多