我有一个返回客户列表的非常基本的 Controller 方法。我希望它在用户浏览时返回 ListView ,并将 JSON 返回给在 Accept header 中具有 application/json
的请求。
在 ASP.NET Core MVC 1.0 中这可能吗?
我已经试过了:
[HttpGet("")]
public async Task<IActionResult> List(int page = 1, int count = 20)
{
var customers = await _customerService.GetCustomers(page, count);
return Ok(customers.Select(c => new { c.Id, c.Name }));
}
但默认情况下返回 JSON,即使它不在接受列表中。如果我在浏览器中点击“/customers”,我会得到 JSON 输出,而不是我的 View 。
我想我可能需要编写一个处理 text/html
的 OutputFormatter,但我不知道如何从OutputFormatter
,因为这些方法在 Controller
上,我需要知道要呈现的 View 的名称。
有没有我可以调用的方法或属性来检查 MVC 是否能够找到要呈现的 OutputFormatter
?类似于以下内容:
[HttpGet("")]
public async Task<IActionResult> List(int page = 1, int count = 20)
{
var customers = await _customerService.GetCustomers(page, count);
if(Response.WillUseContentNegotiation)
{
return Ok(customers.Select(c => new { c.Id, c.Name }));
}
else
{
return View(customers.Select(c => new { c.Id, c.Name }));
}
}
最佳答案
我认为这是一个合理的用例,因为它可以简化从单个 Controller 返回 HTML 和 JSON/XML/等的 API 的创建。这将允许渐进增强以及其他一些好处,尽管在 API 和 Mvc 行为需要截然不同的情况下它可能无法很好地工作。
我已经使用自定义过滤器完成了此操作,但有以下注意事项:
public class ViewIfAcceptHtmlAttribute : Attribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.HttpContext.Request.Headers["Accept"].ToString().Contains("text/html"))
{
var originalResult = context.Result as ObjectResult;
var controller = context.Controller as Controller;
if(originalResult != null && controller != null)
{
var model = originalResult.Value;
var newResult = controller.View(model);
newResult.StatusCode = originalResult.StatusCode;
context.Result = newResult;
}
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
}
}
可以添加到 Controller 或操作:
[ViewIfAcceptHtml]
[Route("/foo/")]
public IActionResult Get(){
return Ok(new Foo());
}
或者在 Startup.cs 全局注册
services.AddMvc(x=>
{
x.Filters.Add(new ViewIfAcceptHtmlAttribute());
});
这适用于我的用例,并实现了从同一 Controller 支持 text/html 和 application/json 的目标。我怀疑这不是“最佳”方法,因为它避开了自定义格式化程序。理想情况下(在我看来),这段代码只是另一个 Formatter,如 Xml 和 Json,但它使用 View 渲染引擎输出 Html。不过,该界面有点复杂,这是目前最简单的方法。
关于c# - 我可以在 ASP.NET Core 中使用 Content Negotiation 向浏览器返回 View 并向 API 调用返回 JSON 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40300616/