我正在为HTML编写媒体类型格式化程序,以根据用户的html请求自动生成Razor视图。我这样做是为了在SelfHosted服务中使用。我需要检测请求的控制器/操作,以允许我选择要渲染的视图。
public class RazorHtmlMediaTypeFormatter : MediaTypeFormatter
{
public RazorHtmlMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
public override bool CanWriteType(Type type)
{
return true;
}
public override bool CanReadType(Type type)
{
return false;
}
public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, System.Net.TransportContext transportContext)
{
return Task.Factory.StartNew(() =>
{
var view = Razor.Resolve(String.Format("{0}.{1}.cshtml", something.Controller, something.Action), value);
byte[] buf = System.Text.Encoding.Default.GetBytes(view.Run(new ExecuteContext()));
stream.Write(buf, 0, buf.Length);
stream.Flush();
});
}
}
答案 0 :(得分:6)
为什么不将您返回的对象包装在Metadata<T>
?
即。返回,而不是MyCustomObject
,Metadata<MyCustomObject>
。作为元数据属性,您可以设置控制器名称和操作。然后在格式化程序中,只需将元数据和自定义对象分离,然后仅序列化该自定义对象。
我在这里写了一篇关于这种方法的博客 - http://www.strathweb.com/2012/06/extending-your-asp-net-web-api-responses-with-useful-metadata/。虽然本文的目的略有不同,但我相信您可以将其与您的需求联系起来。
修改:或者如果您对小型黑客没问题,请使用自定义过滤器和标题:
public override void OnActionExecuting(HttpActionContext actionContext) { actionContext.Response.Headers.Add("controller", actionContext.ActionDescriptor.ControllerDescriptor.ControllerName); actionContext.Response.Headers.Add("action", actionContext.ActionDescriptor.ActionName;); base.OnActionExecuting(actionContext); }
然后只是从格式化程序中的标题中读取它,并删除标题条目,以便它们不会被发送到客户端。
答案 1 :(得分:1)
Web API Contrib在here中有一个工作的RazorViewFormatter。