2013-07-17 46 views
3

嗨,大家好我燒燬了谷歌試圖建立某種類,將確定UNIVERSALLY如果它是一個AJAX調用或子動作或行動,以便我的控制器可以確定是否返回部分視圖或全視圖。到目前爲止,我沒有太多運氣。目前我使用下面的代碼來實現這一返回部分視圖,如果行動是ajax或兒童行動普遍

if (Request.IsAjaxRequest() || ControllerContext.IsChildAction) 
      { 
       return PartialView(); 
      } 
return View(); 

問題是你必須這樣做,在一個控制器和每一個條件,你遇到的每一個動作,但我相信,有一種方法來實現這一目標通過一個幫手,但不知道如何。你能指點我的任何鏈接/示例代碼來實現這一點。

編輯:

@Aron我已經發布了一段代碼作爲整個控制器就太長了。但你可以看到我的困境。返回包含一個視圖和一個對象/模型「k」。

public ActionResult _Details_Message(int id = 0, int CId = 0) 
     { 
      ViewBag.MrnSortParm = CId; 
      if (id != 0) 
      { 
       var k = mrn.MRNS.Where(u => u.Id == id).SingleOrDefault(); 
       if (k.To == User.Identity.Name) 
       { 
        if (k.Type == 0) // message 
        { 
         k.Read = true; 
         mrn.Entry(k).State = EntityState.Modified; 
         mrn.SaveChanges(); 
        } 
        return PartialView("_Details_Message", k);//replace the above code here 
       } 
       if (k.From == User.Identity.Name) 
       { 
        return PartialView("_Sent", k); //replace the above code here 
       } 
      } 
      var m = new message(); 
      m.CourierId = CId; 
      return PartialView("_Create_Message", m); //replace the above code here 
     } 

編輯2 我已經找到了答案它不是一個輔助功能,但在視圖中修改。鏈接是here。可以將我自己的問題標記爲重複:(

+0

這會讓你的代碼在一個私人貼什麼方法並返回一個呼叫給它? –

+0

問題在於何時使用視圖返回模型。例如'返回視圖(「someview」,somemodel);'所以如果我構造一個方法,我將不得不爲每個對象/模型重複構造相同的方法,這種方法會破壞方法的目的。另一方面,我可能會嘗試變種 –

+0

。 –

回答

6

那麼你很幸運,因爲我寫了一個TON代碼來做類似的事情,這也考慮到了,如果你想返回模型作爲JSON對象或視圖。它還將所有的Ajax調用包裝到一個包裝響應元素中,基本上如果你有一個UI人員​​做東西,你永遠不需要知道他想要什麼,讓他編寫視圖或者調用AJAX調用,這完全分離來自C#開發人員的UI人員(只要他了解如何編寫MVC Views,他根本不需要知道控制器是如何工作的,只需通過該模型即可)

ControllerBase cla SS:

public abstract class MyControllerBase : Controller 
{ 
    // could be moved to web.config 
    private const _jsonDataType = "JsonDataType"; 

    public bool IsAjaxRequest 
    { 
     get 
     { 
      return this.HttpContext.Request.IsAjaxRequest(); 
     } 
    } 

    public bool IsAjaxHtmlRequest 
    { 
     get 
     { 
      return string.Equals(this.Request.Headers[MyControllerBase._jsonDataType], "html", StringComparison.CurrentCultureIgnoreCase); 
     } 
    } 

    private JsonResponse GetAjaxResponse() 
    { 
     JsonResponse result = new JsonResponse(); 
     result.IsValid = true; 
     return result; 
    } 

    private JsonResponse<T> GetAjaxResponse<T>(T model) 
    { 
     JsonResponse<T> result = new JsonResponse<T>(); 
     result.Data = model; 
     result.IsValid = true; 
     return result; 
    } 

    private JsonResponse<string> GetAjaxHtmlResponse() 
    { 
     JsonResponse<string> result = new JsonResponse<string>(); 
     result.Data = this.PartialViewToString(this.ControllerContext.RouteData.Values["Action"].ToString(), null); 
     result.IsValid = true; 
     return result; 
    } 

    private JsonResponse<string> GetAjaxHtmlResponse<T>(T model) 
    { 
     JsonResponse<string> result = new JsonResponse<string>(); 
     result.Data = this.PartialViewToString(this.ControllerContext.RouteData.Values["Action"].ToString(), model); 
     result.IsValid = true; 
     return result; 
    } 

    private JsonResponse<string> GetAjaxHtmlResponse<T>(T model, string viewName) 
    { 
     JsonResponse<string> result = new JsonResponse<string>(); 
     result.Data = this.PartialViewToString(viewName, model); 
     result.IsValid = true; 
     return result; 
    } 

    public ActionResult ViewOrAjax() 
    { 
     return this.ViewOrAjax(JsonRequestBehavior.DenyGet); 
    } 

    public ActionResult ViewOrAjax(JsonRequestBehavior jsonRequestBehavior) 
    { 
     if (this.ControllerContext.IsChildAction) 
     { 
      return this.PartialView(this.ControllerContext.RouteData.Values["Action"].ToString(), null); 
     } 

     if (this.IsAjaxRequest) 
     { 
      if (this.IsAjaxHtmlRequest) 
      { 
       return this.Json(this.GetAjaxHtmlResponse(), jsonRequestBehavior); 
      } 
      return this.Json(this.GetAjaxResponse(), jsonRequestBehavior); 
     } 

     return this.View(this.ControllerContext.RouteData.Values["Action"].ToString(), null); 
    } 

    public ActionResult ViewOrAjax<T>(T model) 
    { 
     return this.ViewOrAjax<T>(model, JsonRequestBehavior.DenyGet); 
    } 

    public ActionResult ViewOrAjax<T>(T model, JsonRequestBehavior jsonRequestBehavior) 
    { 
     if (this.ControllerContext.IsChildAction) 
     { 
      return this.PartialView(model); 
     } 

     if (this.IsAjaxRequest) 
     { 
      if (this.IsAjaxHtmlRequest) 
      { 
       return this.Json(this.GetAjaxHtmlResponse(model), jsonRequestBehavior); 
      } 
      return this.Json(this.GetAjaxResponse<T>(model), jsonRequestBehavior); 
     } 

     return this.View(model); 
    } 

    public ActionResult ViewOrAjax<T>(IView view, T model, JsonRequestBehavior jsonRequestBehavior) 
    { 
     if (this.ControllerContext.IsChildAction) 
     { 
      return this.PartialView(model); 
     } 

     if (this.IsAjaxRequest) 
     { 
      if (this.IsAjaxHtmlRequest) 
      { 
       return this.Json(this.GetAjaxHtmlResponse(model), jsonRequestBehavior); 
      } 
      return this.Json(this.GetAjaxResponse<T>(model), jsonRequestBehavior); 
     } 

     return this.View(view, model); 
    } 
    public ActionResult ViewOrAjax<T>(string viewName, T model) 
    { 
     return this.ViewOrAjax<T>(viewName, model, JsonRequestBehavior.DenyGet); 
    } 
    public ActionResult ViewOrAjax<T>(string viewName, T model, JsonRequestBehavior jsonRequestBehavior) 
    { 
     if (this.ControllerContext.IsChildAction) 
     { 
      return this.PartialView(model); 
     } 

     if (this.IsAjaxRequest) 
     { 
      if (this.IsAjaxHtmlRequest) 
      { 
       return this.Json(this.GetAjaxHtmlResponse(model, viewName), jsonRequestBehavior); 
      } 
      return this.Json(this.GetAjaxResponse<T>(model), jsonRequestBehavior); 
     } 

     return this.View(viewName, model); 
    } 
    public ActionResult ViewOrAjax<T>(string viewName, string masterName, T model) 
    { 
     return this.ViewOrAjax<T>(viewName, masterName, model, JsonRequestBehavior.DenyGet); 
    } 
    public ActionResult ViewOrAjax<T>(string viewName, string masterName, T model, JsonRequestBehavior jsonRequestBehavior) 
    { 
     if (this.ControllerContext.IsChildAction) 
     { 
      return this.PartialView(model); 
     } 

     if (this.IsAjaxRequest) 
     { 
      if (this.IsAjaxHtmlRequest) 
      { 
       return this.Json(this.GetAjaxHtmlResponse(model, viewName), jsonRequestBehavior); 
      } 
      return this.Json(this.GetAjaxResponse(model), jsonRequestBehavior); 
     } 

     return this.View(viewName, masterName, model); 
    } 

    protected internal new ViewResult View(string viewName, string masterName, object model) 
    { 
     if (model != null) 
     { 
      ViewData.Model = model; 
     } 

     ViewResult result = new ViewResult 
     { 
      ViewName = viewName, 
      MasterName = masterName, 
      ViewData = ViewData, 
      TempData = TempData 
     }; 

     return result; 
    } 
} 

適合於Ajax的JsonResponse<>全球包裝呼叫:

public class JsonResponse 
{ 
    public JsonResponse() 
    { 
    } 

    public bool IsValid { get; set; } 
    public bool IsAjaxRequestUnsupported { get; set; } 
    public string RedirectTo { get; set; } 
    public string CanonicalUrl { get; set; } 
} 

public class JsonResponse<T> : JsonResponse 
{ 
    public JsonResponse() : base() 
    { 
    } 

    public T Data { get; set; } 
} 

的JavaScript global_getJsonResponse代碼(需要的jQuery):

function global_getJsonResult(Controller, View, data, successCallback, completeCallback, methodType, returnType, jsonDataType) { 
    if (IsString(Controller) 
     && IsString(View) 
     && !IsUndefinedOrNull(data)) { 
     var ajaxData; 
     var ajaxType; 

     if (typeof (data) == "string") { 
      ajaxData = data; 
      ajaxType = "application/x-www-form-urlencoded" 
     } 
     else { 
      ajaxData = JSON.stringify(data); 
      ajaxType = "application/json; charset=utf-8"; 
     } 

     var method = 'POST'; 

     if (methodType) { 
      method = methodType; 
     } 

     var dataType = 'json'; 
     if (returnType) { 
      dataType = returnType; 
     } 
     var jsonType = 'html'; 
     if (jsonDataType) { 
      jsonType = jsonDataType; 
     } 

     var jqXHR = $.ajax({ 
      url: '/' + Controller + '/' + View, 
      headers: { JsonDataType: jsonType }, 
      data: ajaxData, 
      type: method, 
      dataType: dataType, 
      contentType: ajaxType, 
      success: function (jsonResult) { 
       if (!IsUndefinedOrNull(jsonResult) 
        && jsonResult.hasOwnProperty("RedirectTo") 
        && !IsUndefinedOrNull(jsonResult.RedirectTo) 
        && jsonResult.RedirectTo.length > 0) { 
        $.fn.notify('error', 'Login Expired', 'You have been inactive for a prolonged period of time, and have been logged out of the system.'); 
        window.setTimeout(function() { window.location = jsonResult.RedirectTo }, 5000); 
       } 
       else if (IsFunction(successCallback)) { 
        successCallback(jsonResult, Controller + '/' + View); 
       } 
      }, 
      error: function (jqXHR, textStatus, errorThrown) { 
       if (errorThrown != 'abort') { 
        $.fn.notify('error', 'Whoops! Something went wrong.', 'We have been notified of the error.'/* textStatus + ': ' + errorThrown*/); 
       } 

       log('ERROR IN global_getJsonResult() : ', textStatus, errorThrown, jqXHR); 
      }, 
      complete: function (jqXHR, textStatus) { 
       if (IsFunction(completeCallback)) { 
        completeCallback(jqXHR, textStatus, Controller + '/' + View); 
       } 
      } 
     }); 

     return jqXHR; 
    } 
} 

該代碼同時支持服務器端和客戶端超時通過Handling session timeout in ajax calls,改變如下:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
{ 
    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    { 
    filterContext.Result = new JsonResult 
    { 
     Data = new JsonResponse<bool> 
     { 
     IsValid = false, 
     RedirectTo = FormsAuthentication.LoginUrl 
     }, 
     JsonRequestBehavior = JsonRequestBehavior.AllowGet 
    }; 
    } 
    else 
    { 
    base.HandleUnauthorizedRequest(filterContext); 
    } 
} 

一對夫婦控制器擴展方法,讓你恢復文本渲染的局部視圖,在JSON(此代碼是從SO,我通常記錄這些,但我失去了它):

internal static class ControllerExtensions 
{ 
    public static string PartialViewToString(this Controller instance, object model) 
    { 
    string viewName = instance.ControllerContext.RouteData.GetRequiredString("action"); 

    return ControllerExtensions.PartialViewToString(instance, viewName, model); 
    } 

    public static string PartialViewToString(this Controller instance, string viewName, object model) 
    { 
    string result; 

    ViewDataDictionary viewData = instance.ViewData; 
    viewData.Model = model; 

    using (var sw = new StringWriter()) 
    { 
     var viewResult = ViewEngines.Engines.FindPartialView(instance.ControllerContext, viewName); 

     var viewContext = new ViewContext(instance.ControllerContext, viewResult.View, viewData, instance.TempData, sw); 
     viewResult.View.Render(viewContext, sw); 

     viewResult.ViewEngine.ReleaseView(instance.ControllerContext, viewResult.View); 
     result = sw.GetStringBuilder().ToString(); 
} 

    return result; 
    } 
} 

現在推導(可悲的是)所有的控制器從這個基本控制器:

public HomeController : MyBaseController 
{ 
    public ActionResult Index() 
    { 
    var viewModel = new MyViewModel(); 

    return this.ViewOrAjax(viewModel); 
    } 
} 

現在,如果頁面被瀏覽器調用作爲標準的GET,你得到一個佈局(又名this.View(viewModel))通常呈現的頁面。

如果你把它通過JavaScript的使用Ajax:

global_getJsonResult("Home", // Controller or 'Area/Home' for areas 
    "Index",     // View 
    $('#form').serialize(),  // Json object or a serialized Form 
    jsCallBack,     // call back function or null 
    "Post",      // Get or Post 
    "Html");     // "Html" to return a Partial View in "Data" 
           // or "Json" to return a serialized view model in "Data" 
+0

謝謝埃裏克。我會盡量使你的代碼適合我的。 +1 –

+0

還在爲你更新,這是相當大的... –

+0

好吧,應該是相當完整的,讓我知道是否缺少一些東西。 –

8

一個簡單的解決方案,可以爲您所使用的_ViewStart.cshtml文件瀏覽文件夾下的類似的代碼:

@{ 
    Layout = Request.IsAjaxRequest() || ViewContext.IsChildAction 
     ? null 
     : "~/Views/Shared/_Layout.cshtml"; 
} 

隨着該代碼你可以從你的所有行動只需return View();

由於所有觀點都經歷了這一步,那可能就是您的通用解決方案。

+0

嘿,這是一個很好的解決方案 –

+0

簡單而有效,謝謝 – Lars

+0

除了如果你有多個佈局文件在View文件本身而不是在_ViewStart.cshtml中設置。在這種情況下,您需要重複上述幾次打破DRY原則。在這些情況下,您可以創建一個從'System.Web.Mvc.WebViewPage'繼承的自定義WebViewPage類 – hofnarwillie

1

對梅德的回答改進:

創建一個自定義WebViewPage類,這樣你就不需要修改添加到多個視圖(相關,其中有哪些是由視圖本身,而不是_ViewStart確定的多個佈局文件文件)

public abstract class CustomWebViewPage: WebViewPage 
{ 
    public override string Layout 
    { 
     get 
     { 
      return Request.IsAjaxRequest() || ViewContext.IsChildAction ? null : base.Layout; 
     } 
     set 
     { 
      base.Layout = value; 
     } 
    } 
} 

public abstract class CustomWebViewPage<TModel>: CustomWebViewPage 
{ 
} 

而且在web.config(Views文件夾下)

<pages pageBaseType="Fully.Qualified.Namespace.CustomWebViewPage"> 
+1

這應該是被接受的答案。 –