這在標準的MVC中應該很容易。考慮一個控制器動作:
public ActionResult SomeAction(SomeModel request)
{
// based on the request, return a response
}
這個動作可以返回任何ActionResult
,無所謂哪一個。因此,在一個代碼路徑,你可以有:
return View(someViewModel);
而在另一個你可能有:
return Json(someViewModel);
第一個將控制權交給它將使用剃刀,並返回一個網頁正常視圖,第二個只會返回帶有序列化數據的JSON響應。
您如何確定代碼路徑取決於您,但正如您所說,這可以通過基於頭的內容協商完成。您可以可以直接在控制器中檢查標題,但是可能會將控制器耦合到對測試不太好的HTTP上下文。
如果會出現很多這樣的動作,或許一個優雅的方法是將自定義模型綁定器添加到MVC管道中,該管道本身檢查頭信息並將其傳遞給控制器。
所以,你的控制器動作(或多個)可以簡單地得到另一個參數:
public ActionResult SomeAction(HeaderInfo headers, SomeModel request)
{
// based on the values in "headers", return a response
}
HeaderInfo
可以只是一個簡單的自定義類,它甚至可能只是一個布爾它對於初學者:
public class HeaderInfo
{
public bool ReturnDataOnly { get; set; }
}
基於該布爾的狀態,控制器返回整個視圖或僅返回數據(JSON)。然後,您可以將自定義模型綁定器注入到管道中,以自動將此綁定到包含它的所有請求。這種粘合劑可能是如此簡單:
public class HeaderInfoBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (bindingContext == null)
throw new ArgumentNullException("bindingContext");
var result = new HeaderInfo();
// examine the contexts for headers, based on those headers
// set true or false on the object's property
return result;
}
}
然後將其添加到MVC配置bootstrappers(通常在App_Start
):
public class BinderConfig
{
public static void RegisterBinders(ModelBinderDictionary binders)
{
binders[typeof(HeaderInfo)] = new HeaderInfoBinder();
}
}
並調用從應用開始在Global.asax.cs
這個配置:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
BinderConfig.RegisterBinders(ModelBinders.Binders); // <-- right there
經過這些少許調整,應用程序中任何具有HeaderInfo
參數的控制器動作都會自動根據該HeaderInfoBinder
中的邏輯,在運行時填充該參數,您可以根據自己的情況對其進行調整和添加。然後,任何控制器操作都可以檢查該對象以確定返回的內容。 (這可能會導致大量重複的switch
塊,您可能會進一步重構爲某個通用幫助程序。)
哇!很好的答案。如果我切換到MVC並不意味着我失去了例如IContentNegotiator,基於動詞的路由約定,OAuth認證等WebAPI的好處?從概念上講,我們認爲這是一個API,而不是一個「web應用程序」(在這個詞的普通asp.net意義上)。 – goofballLogic
@goofballLogic:WebAPI中存在類似的功能。例如,對於自定義聯編程序,您可以編寫類似的東西(不同的基類和不同的配置引導程序),並使用參數屬性告訴WebAPI方法使用該聯編程序。 *假設*新版本(下一版本)以更加優雅的方式結合了MVC和WebAPI,而傳統上兩者雖然有些相似但框架管道相當類似。我不確定這是否意味着WebAPI很容易返回視圖,我從來沒有這樣做過。所有的概念應該是相同的。 – David