在ASP.NET MVC网站上构建API

Pau*_*ell 2 asp.net api rest asp.net-mvc

我有一个现有的ASP.NET MVC网站,其行为如下:

public ActionResult Show(int id)
{
    var customer = GetCustomer(id);

    return View(new ShowCustomerModel(customer));
}
Run Code Online (Sandbox Code Playgroud)

我现在需要能够将这些操作作为API的一部分执行,该API将从第三方应用程序调用.理想情况下,操作看起来像:

public ActionResult Get(int id)
{
    var customer = GetCustomer(id);

    return Json(new CustomerResource(customer));
}
Run Code Online (Sandbox Code Playgroud)

问题是,存在哪些ASP.NET MVC工具或模式允许我将它们组合在一起 - 例如,Rails允许我指定多种返回格式:

def index
  @customer = get_customer(...)

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @customer}
    format.json { render :json => @customer}
  end
end
Run Code Online (Sandbox Code Playgroud)

这甚至是一个很好的模式吗?我应该只是:

public Customer Get(int id)
{
    return GetCustomer(id);
}
Run Code Online (Sandbox Code Playgroud)

并使用动作过滤器有选择地呈现为JSON或视图?

Aar*_*ell 8

我创建了一个ActionResult足够聪明的东西,根据提供的Accept Headers确定你想要什么样的结果,如下所示:

public class AdaptiveActionResult : ActionResult
{
    private readonly object _model;

    public AdaptiveActionResult(object model)
    {
        _model = model;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var accept = context.HttpContext.Request.AcceptTypes;
        if (accept == null || !accept.Contains("application/json"))
        {
            var viewResult = new ViewResult {ViewData = new ViewDataDictionary(_model)};
            viewResult.ExecuteResult(context);
            return;
        }

        var jsonResult = new JsonResult
                             {
                                 Data = _model, 
                                 JsonRequestBehavior = JsonRequestBehavior.AllowGet
                             };
        jsonResult.ExecuteResult(context);
        return;
    }
}
Run Code Online (Sandbox Code Playgroud)

这可以扩展到检查他们是否需要XML,RSS,Atom,甚至是什么.

然后你可以在你的控制器中这样做:

    public ActionResult Index()
    {
        return new AdaptiveActionResult(new MyModel());
    }
Run Code Online (Sandbox Code Playgroud)


Jus*_*ger 6

您可以设置自定义操作过滤器属性,以在操作执行时捕获内容类型并将其存储到参数中:

public class ContentTypeRequestFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.ActionParameters["contentType"] = 
            filterContext.HttpContext.Request.ContentType;
        base.OnActionExecuting(filterContext);
    }
}  
Run Code Online (Sandbox Code Playgroud)

然后在您的控制器中,您可以修饰您的操作方法,添加参数,并对其进行检查:

[ContentTypeRequestFilter]
public ActionResult Get(int id, string contentType)
{
    var customer = GetCustomer(id);
    if(contentType.ToLower() == "application/json")
    {
        return Json(new CustomerResource(customer));
    }
    return View(new ShowCustomerModel(customer));
}  
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以从那里适应其他内容请求类型(xml等).我在博客文章中采用了类似的方法,在MVC 3中构建REST API架构.