我可以使用内容协商将视图返回给浏览器,并将JSON返回给ASP.NET Core中的API调用吗? [英] Can I use Content Negotiation to return a View to browers and JSON to API calls in ASP.NET Core?

查看:82
本文介绍了我可以使用内容协商将视图返回给浏览器,并将JSON返回给ASP.NET Core中的API调用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常基本的控制器方法,该方法返回客户"列表.我希望它在用户浏览到列表视图时返回列表视图,并返回JSON到在接受标头中具有application/json的请求.

I've got a pretty basic controller method that returns a list of Customers. I want it to return the List View when a user browses to it, and return JSON to requests that have application/json in the Accept header.

在ASP.NET Core MVC 1.0中可能吗?

Is that possible in 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输出,而不是视图.

But that returns JSON by default, even if it's not in the Accept list. If I hit "/customers" in my browser, I get the JSON output, not my view.

我以为我可能需要编写处理text/html的OutputFormatter,但是我不知道如何从OutputFormatter调用View()方法,因为这些方法在Controller上,并且我需要知道要渲染的视图的名称.

I thought I might need to write an OutputFormatter that handled text/html, but I can't figure out how I can call the View() method from an OutputFormatter, since those methods are on Controller, and I'd need to know the name of the View I wanted to render.

是否可以调用一种方法或属性来检查MVC是否能够找到要渲染的OutputFormatter?类似于以下内容:

Is there a method or property I can call to check if MVC will be able to find an OutputFormatter to render? Something like the following:

[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 }));
    }
}

推荐答案

我认为这是一个合理的用例,因为它将简化创建从单个控制器返回HTML和JSON/XML/etc的API的过程.尽管在API和Mvc行为需要截然不同的情况下可能无法很好地工作,但这将允许逐步增强以及其他一些好处.

I think this is a reasonable use case as it would simplify creating APIs that return both HTML and JSON/XML/etc from a single controller. This would allow for progressive enhancement, as well as several other benefits, though it might not work well in cases where the API and Mvc behavior needs to be drastically different.

我已经使用自定义过滤器完成了此操作,以下是一些警告:

I have done this with a custom filter, with some caveats below:

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)
    {

    }
}

可以添加到控制器或动作中的

which can be added to a controller or action:

[ViewIfAcceptHtml]
[Route("/foo/")]
public IActionResult Get(){ 
        return Ok(new Foo());
}

或在Startup.cs中全局注册

or registered globally in Startup.cs

services.AddMvc(x=>
{ 
   x.Filters.Add(new ViewIfAcceptHtmlAttribute());
});

这适用于我的用例,并实现了从同一控制器支持text/html和application/json的目标.我怀疑这不是最佳"方法,因为它避开了自定义格式化程序.理想情况下(在我看来),该代码将是另一个格式化程序,例如Xml和Json,但使用View渲染引擎输出Html.不过,该界面要复杂一些,这是目前最简单的方法.

This works for my use case and accomplishes the goal of supporting text/html and application/json from the same controller. I suspect isn't the "best" approach as it side-steps the custom formatters. Ideally (in my mind), this code would just be another Formatter like Xml and Json, but that outputs Html using the View rendering engine. That interface is a little more involved, though, and this was the simplest thing that works for now.

这篇关于我可以使用内容协商将视图返回给浏览器,并将JSON返回给ASP.NET Core中的API调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆