在 .NET MVC 4 (Web API) 中,如何拦截对控制器的请求并更改其 Content-Type?

Posted

技术标签:

【中文标题】在 .NET MVC 4 (Web API) 中,如何拦截对控制器的请求并更改其 Content-Type?【英文标题】:In .NET MVC 4 (Web API), how do I intercept a request for a controller and change it's Content-Type? 【发布时间】:2012-12-31 05:12:48 【问题描述】:

感谢收看!

背景

我正在为一家公司编写一个 API 层,供不同的应用程序和外部消费者使用。

在消费端,大部分消费者会使用jQuery$.post()通过ajax调用服务;然而,Internet Explorer 让我们的生活更具挑战性(当然!)。对于 IE,我必须使用 XDomainRequest 对象,因为 IE 不会运行 jQuery $.post(),而且如果我使用 IE 的 XMLHttpRequest(),我会收到一条不可接受的安全消息(再次——当然!):

否则,XMLHttpRequest() 工作正常。

我正在使用 C#、.NET MVC 4 (WebApi)

问题

问题在于XDomainRequest 不允许您设置Content-Type 标头,并且始终默认为text-plain,这是MVC 4 WebApi 控制器将不接受的(再一次——当然!!)。

问题

如何拦截对我的控制器的请求,检测text-plain 内容类型的存在并将它们即时更改为text-json 内容类型?

提前致谢!

【问题讨论】:

"因为 IE 不会运行 jQuery $.post()" 你确定吗? 我使用的是 IE 8,但它似乎没有这样做,可能是因为它是跨域的。让我再检查一下。 . . 看了一圈后,尝试在帖子 url 的末尾添加一个缓存破坏参数:例如$.post("my/url?d=" + new Date().getMilliseconds().....) @BFree--是的。在 IE8 中,我可以在$.post() 上设置一个断点,它会被命中,但回调函数永远不会执行。就好像 IE 只是跨过.post()。相同的.post() 代码在其他浏览器中运行良好。 @Bfree--好的,尝试了 cacheBuster,但遗憾的是没有帮助。 【参考方案1】:

两天后,翻阅文档并阅读此线程,我已经能够完成这项工作。所以如果我对解决方案的描述很差,请原谅我;这是我第一次回答这些类型的线程之一。因为我花了很长时间才找到问题,所以我认为值得拯救一些人,以免陷入同样的​​问题。

我的帮助来源来自byterot的上述链接。

    我做的第一件事是创建一个DelegatingHandler。因此,在我的帮助文件夹或每个您想要创建一个类的地方,并按您的意愿命名。 这是我的:

    public class ContentTypeHandler : DelegatingHandler
    
        /** Check that this is an IE browser. */
        if ((request.Headers.UserAgent.ToString().IndexOf("MSIE", System.StringComparison.Ordinal) > -1))
        
            MediaTypeHeaderValue contentTypeValue;
            if (MediaTypeHeaderValue.TryParse("application/json", out contentTypeValue))
            
                request.Content.Headers.ContentType = contentTypeValue;
                request.Content.Headers.ContentType.CharSet = "utf-8";
            
        
    
        /** Return request to flow. */
        return base.SendAsync(request, cancellationToken)
           .ContinueWith(task =>
           
                // work on the response
                var response = task.Result;
                return response;
           );
    
    

    最后认为你必须做的是在你的Application_Start() 中调用Global.asax.cs 文件中的处理程序:

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

这就是我所做的一切,它奏效了。祝你好运,我希望这对某人有所帮助。

【讨论】:

【参考方案2】:

在 HTTP 堆栈中修改请求没有问题。它可以通过在到达控制器之前编写和注册您的自定义DelegatingHandler 来完成。委托处理程序可以在游戏的早期处理此问题,因此您的请求将以您想要的形式到达控制器。它也可以是特定于路由的处理程序。 http://msdn.microsoft.com/en-us/library/system.net.http.delegatinghandler.aspx

您是否尝试过使用 $.ajax 而不是 $.post ?

【讨论】:

是的,我已经尝试过各种 jQuery 帖子、ajacx 等。似乎 IE 根本不允许通过 jquery 进行跨域 ajax 帖子。我很欣赏在委派处理程序上指向 msdn 文档的链接,但如果您有示例代码,那就太好了。 这是很好的委托处理程序源代码byterot.blogspot.com/search?q=delegatinghandler

以上是关于在 .NET MVC 4 (Web API) 中,如何拦截对控制器的请求并更改其 Content-Type?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 4,Web API - 404 未找到

正确处理 ASP.net MVC 4 Web Api 路由中的嵌套资源

ASP.Net MVC 4 Web API 控制器不适用于 Unity.WebApi

在 .NET MVC 4 (Web API) 中,如何拦截对控制器的请求并更改其 Content-Type?

无法使用 ASP.NET (MVC 4) Web API OData Prerelease 加载文件或程序集 System.Net.Http,版本 = 4.0.0.0

使用成员资格提供程序的 ASP.NET MVC 4 Web API 身份验证