2011-11-17 32 views
2

我有一個現有的ASP.NET MVC的網站,像這樣的動作:大廈的API在ASP.NET MVC網站

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

    return View(new ShowCustomerModel(customer)); 
} 

我現在需要執行這些操作的API的一部分的能力,這將是從第三方應用程序調用。理想情況下,動作看起來像:

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

    return Json(new CustomerResource(customer)); 
} 

的問題是,什麼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 

這是一個很好的模式嗎?我應該也許只是有:

public Customer Get(int id) 
{ 
    return GetCustomer(id); 
} 

並使用操作篩選器選擇性呈現爲JSON或視圖?

回答

8

我想創建一個ActionResult可以足夠聰明,以確定您在此基礎上提供,像這樣的接受頭想要什麼樣的結果:

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

這可以擴展以檢查如果他們想要XML,RSS,Atom,什麼都可以。

然後你就可以做到這一點在你的控制器像這樣:

public ActionResult Index() 
    { 
     return new AdaptiveActionResult(new MyModel()); 
    } 
+0

這是一個非常酷的方法! –

3

它可能不是您想要的,但您可以檢查請求類型並採取相應措施。

public ActionResult Get(int id) 
{ 
    if (Request.IsAjaxRequest) 
    { 
     // do stuff 
     return new JsonResult(new { Foo = "Foo", Bar = "Bar" }); 
    } 
    else 
    { 
     // do stuff 
     return View(myModel); 
    } 

    // if you need beyond IsAjaxRequest, you could 
    // check the controller's Request object for other 
    // indicators as to what type of result to 
    // send back 
} 
1

您可以爲每一個3個行動和創建一個自定義屬性,並創建一個ActionInvoker只是喜歡的方式HttpPost和HTTPGET工作

[JsonRequest] 
[ActionName("Get")] 
public ActionResult GetAsJson(int id) { 
    //return as Json 
} 

[XmlRequest] 
[ActionName("Get")] 
public ActionResult GetAsXml(int id) { 
    //return as xml 
} 

public ActionResult Get(int id) { 
    //get stuff normally 
} 

這顯然需要編碼,以獲得工作的一個位,但將可重複使用。

另一種方法是創建一個CustomerResult對象,只是有一個動作,做丹尼爾上面提到的,但這個邏輯可以放入您CustomerResult對象。

6

你可以建立一個自定義操作過濾器屬性趕內容類型的操作執行時並存儲到一個參數:

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

然後在你的控制器,你可以裝飾你的操作方法,添加參數,並做一個檢查:

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

從那裏你可以適應其他內容請求類型(XML等),如果需要。我在Building a REST API architecture in MVC 3上的博客文章中採取了類似的方法。

+0

+1請求過濾器是去這裏的最佳方式。 –

3

@Schwarty's answer是最好的,如果你想你的網站內堅持並執行AUTOMAGIC紅寶石的事情。

但我建議你建立一個單獨的前端的API。主要問題是版本控制 - 你真的不應該發佈不可版本化的api。我們人類閱讀網頁可以很容易地適應更新的數據模型。也許不容易,但是當事情發生變化時我們通常不會中斷。然而,您的API的消費者是經常與您的特定實現綁定並且不喜歡更改的機器。

簡短版本:它們是單獨的任務,應在大多數情況下單獨處理。

+0

我同意API的一個單獨的接口點將是一個好方法。您可以在您的MVC應用程序中爲您的API創建一個新的區域,並且仍然在站點和API中使用相同的數據和業務邏輯。 –

+0

或者只是引用相同核心程序集的另一個項目。 。 。 –

+0

這實際上就是我最終做的 - 一個提供JSON的WCF WebApi服務的a/api路由。 –