ASP.NET MVC 4/Web API-插入Razor渲染器以接受:text/html

ASP.NET MVC 4/Web API-插入Razor渲染器以接受:text/html,razor,asp.net-mvc-4,asp.net-web-api,content-negotiation,Razor,Asp.net Mvc 4,Asp.net Web Api,Content Negotiation,我正在使用ASP.NETMVC4WebAPI创建一个RESTfulWeb服务。对于API访问,我返回JSON,但一旦一切正常,默认情况下,内容协商应该适用于XML和JSON 由于我正在努力实现一个真正以RESTful资源为中心的web服务,所以我的URI将指向实际的资源。如果请求中出现Accepts:text/HTML,我想通过返回资源的HTML表示来利用这一点(就像在浏览器中抛出链接) 我希望能够利用MVC4WebAPI的内容协商来插入一个使用Razor模板的文本/html渲染器。有没有这样做

我正在使用ASP.NETMVC4WebAPI创建一个RESTfulWeb服务。对于API访问,我返回JSON,但一旦一切正常,默认情况下,内容协商应该适用于XML和JSON

由于我正在努力实现一个真正以RESTful资源为中心的web服务,所以我的URI将指向实际的资源。如果请求中出现
Accepts:text/HTML
,我想通过返回资源的HTML表示来利用这一点(就像在浏览器中抛出链接)

我希望能够利用MVC4WebAPI的内容协商来插入一个使用Razor模板的文本/html渲染器。有没有这样做的工作实例


是的,这是连接“常规”MVC页面和Web API的桥梁。基本上,我想创建一个渲染器,它使用基于约定的方法来查找和渲染Razor视图,就像“常规”MVC一样。我可以提出基于约定的视图查找逻辑我只是在寻找a)全局插入我的
文本/html
呈现程序到内容协商中,以及b)使用Razor引擎手动将我的模型呈现为html。

Fredrik Normén有一篇关于这个主题的博客文章:

基本上,您需要创建一个
MediaTypeFormatter

using System;
using System.Net.Http.Formatting;

namespace WebApiRazor.Models
{
    using System.IO;
    using System.Net;
    using System.Net.Http.Headers;
    using System.Reflection;
    using System.Threading.Tasks;

    using RazorEngine;

    public class RazorFormatter : MediaTypeFormatter
    {
        public RazorFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xhtml+xml"));
        }

        //...

        public override Task WriteToStreamAsync(
                                                Type type,
                                                object value,
                                                Stream stream,
                                                HttpContentHeaders contentHeaders,
                                                TransportContext transportContext)
        {
            var task = Task.Factory.StartNew(() =>
                {
                    var viewPath = // Get path to the view by the name of the type

                    var template = File.ReadAllText(viewPath);

                    Razor.Compile(template, type, type.Name);
                    var razor = Razor.Run(type.Name, value);

                    var buf = System.Text.Encoding.Default.GetBytes(razor);

                    stream.Write(buf, 0, buf.Length);

                    stream.Flush();
                });

            return task;
        }
    }
}
然后在Global.asax中注册:

GlobalConfiguration.Configuration.Formatters.Add(new RazorFormatter());
上面的代码是从博客文章中复制的,不是我的作品

你可以看一下。这与Kyle的答案非常相似,但是这是一个全面的开源项目,有更多的特性、单元测试等等。你也可以这样做


我会说,它肯定需要更多的功能,但他们似乎设计得很好,因此很容易为它做出贡献。

重定向到Html的普通控制器是可以接受的(或者通过HttpRequest执行另一个操作并将结果发送回客户端)?@KyleTrauberman,我更愿意参与内容谈判。至少从我有限的理解来看,这在架构上是最明智的做法。我猜Web API和常规MVC将来会结合在一起,我将把赌注押在Web API基础设施上,因此构建内容协商框架似乎是正确的选择。重定向到另一个控制器可能会起作用,但我的经验让我相信这将是不自然的,并在将来造成麻烦。但我并不反对理解这将如何运作:)