NancyFx conneg从IResponseProcessor返回406,文本/ html内容类型除外

时间:2014-02-27 06:37:07

标签: owin mime-types nancy plaintext content-negotiation

我在 Microsoft.Owin.Host.IIS (Helios)上运行Nancy。

我正在尝试通过IResponseProcessor连接到连接,以响应Accept的{​​{1}}标头,但它只返回406.

我尝试了多种内容类型,但没有任何效果....除了奇怪的是text/plain(在清除基础text/html之后)。

ViewProcessor

然后,在模块中:

public class ViewApiProcessor : IResponseProcessor
{
    private readonly IViewFactory viewFactory;

    public ViewApiProcessor(IViewFactory _viewFactory)
    {
        this.viewFactory = _viewFactory;
    }

    private static readonly IEnumerable<Tuple<string, MediaRange>> extensionMappings =
    new[] { new Tuple<string, MediaRange>("txt", MediaRange.FromString("text/plain")) };

    public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings
    {
        get { return extensionMappings; }
    }

    public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)
    {

        bool matchingContentType =
            requestedMediaRange.Matches("text/plain");

        return matchingContentType
            ? new ProcessorMatch { ModelResult = MatchResult.DontCare, RequestedContentTypeResult = MatchResult.ExactMatch }
            : new ProcessorMatch();
    }

    public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)
    {
        context.ViewBag.RequestType = "api";

        var response = (Response)this.viewFactory.RenderView(context.NegotiationContext.ViewName, model, GetViewLocationContext(context));

        return response.WithContentType("text/plain");
    }

    private static ViewLocationContext GetViewLocationContext(NancyContext context)
    {
        return new ViewLocationContext
        {
            Context = context,
            ModuleName = context.NegotiationContext.ModuleName,
            ModulePath = context.NegotiationContext.ModulePath
        };
    }
}

更新:我已修改上述代码,以显示Get["/"] = p => { return Negotiate.WithView("Index"); }; IResponseProcessor

的正确组合

Github Source

2 个答案:

答案 0 :(得分:1)

这里更有趣的是,你的路线是什么样的?如果您希望它能够协商响应,那么您需要返回一个`Negotiator``

Get["/"] = _ => {
   return Negotiator.WithModel(...).WithView("foo");
};

如果返回一个普通的Response(或任何可以隐式转换为Response的内容,例如string,int,HttpStatusCode或Action),那么你将完全绕过内容协商,如此处所述{{3} }。

如果您要使用View[..]返回视图,那么您说唯一允许的媒体范围为text/html

答案 1 :(得分:0)

Conneg是一个寻找问题的解决方案:

  

HTTP内容协商有四个轴:格式协商(Accept),字符编码协商(Accept-Charset),自然语言协商(Accept-Language)和压缩协商(Accept-Encoding)。这些轴需要单独讨论。

  • 格式谈判(接受)
  

您不能依赖格式协商作为Web作者,因为总有客户接受他们未声明的内容。由于前一点,如果您是一个浏览器供应商而另一个供应商已经发布了一个浏览器,该浏览器没有声明它支持它支持的内容,那么您也没有理由浪费字节来声明它,因为Web作者无论如何都不能(仅)依赖声明。

  • 通过字符编码进行协商(Accept-Charset)
  

在主流浏览器中,只有Chrome会再发送Accept-Charset

  • 自然语言谈判(接受语言)
  

当网站有多种语言版本时,版本通常不相同。通常,一种语言是网站的主要语言,其他语言版本不完整,过时或低质量。即使每个人都在其浏览器中配置了他们的语言首选项,该人可以阅读的语言组合也会将世界人口划分为相当小的桶,在某些情况下,使语言组合成为识别特定用户或小群体的方式用户由于人们很少配置他们的语言偏好,当有人配置它时,很可能配置变得唯一或几乎唯一识别。这可以被视为隐私问题。

  • 通过压缩进行协商(Accept-Encoding)
  

目前,所有主流浏览器都支持gzip压缩响应。从这个意义上说,这个功能是成功的。但是,每个请求最终都包含23个字节的样板文件,这非常浪费。

<强>参考