完全有可能。
我们可以延长
RazorViewEngine
以下方式:
public class AppViewEngine : RazorViewEngine
{
private const string ApiModeParam = "API__MODE";
public AppViewEngine()
{
//Performance optimization, if we do not need to lookup for vbhtml
FileExtensions = new[] {"cshtml"};
}
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
var apiMode = controllerContext.HttpContext.Request.Params[ApiModeParam];
if (apiMode == null)
{
return base.FindPartialView(controllerContext, partialViewName, useCache);
}
return GetApiResult(apiMode);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
var apiMode = controllerContext.HttpContext.Request.Params[ApiModeParam];
if (apiMode == null)
{
return base.FindView(controllerContext, viewName, masterName, useCache);
}
return GetApiResult(apiMode);
}
private ViewEngineResult GetApiResult(string apiMode)
{
switch (apiMode)
{
case "json":
return new ViewEngineResult(new ApiJsonView(), this);
case "xml":
return new ViewEngineResult(new ApiXmlView(), this);
default:
return new ViewEngineResult(new[] { "API__MODE is not supported" });
}
}
}
现在我们只需要一些观点:
public class ApiJsonView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
viewContext.HttpContext.Response.AddHeader("Content-Type", "application/json");
//Json.NET, normaly included in MVC
var serializer = JsonSerializer.Create();
serializer.Serialize(writer, viewContext.ViewData.Model);
}
}
public class ApiXmlView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
viewContext.HttpContext.Response.AddHeader("Content-Type", "application/xml");
var model = viewContext.ViewData.Model;
var serializer = new DataContractSerializer(model.GetType());
using (var xmlWriter = new XmlTextWriter(writer))
{
serializer.WriteObject(xmlWriter, model);
}
}
}
最后一件事:我们需要登记
global.asax
在
Application_Start
方法:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new AppViewEngine());
现在每一个请求,都附有
?API__MODE=json
正在显示序列化的ViewModel,而不是HTML页。最好的方法,就是:
public ActionResult SomeAction(int id)
{
var model = new ViewModel(); //Obtain model
return View(model)
}