2009-12-10 81 views
9

這是我之前關於將錯誤傳遞迴客戶端的一個previous question的跟進,但也涉及到ModelState。在ASP.Net MVC中,ModelState可以與ajax更新一起使用嗎?

有沒有人成功地使用了Nerd Dinner方法,但使用Ajax?因此,書呆子晚餐會這樣做。

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(int id, FormCollection formValues) 
{ 
    Dinner dinner = dinnerRepository.GetDinner(id); 
    try 
    { 
     UpdateModel(dinner); 
     dinnerRepository.Save(); 
     return RedirectToAction("Details", new { id=dinner.DinnerID }); 
    } 
    catch 
    { 
     foreach (var issue in dinner.GetRuleViolations()) { 
     ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage); 
    } 
     return View(dinner); 
    } 
} 

使用jQuery $就

function hijack(form, callback, errorFunction, format) { 
    $.ajax({ 
     url: form.action, 
     type: form.method, 
     dataType: format, 
     data: $(form).serialize(), 
     success: callback, 
     error: function(xhr, textStatus, errorThrown) { 
      errorFunction(xhr, textStatus, errorThrown); 
     } 
    }); 
} 

阿賈克斯,控制器的 「試試看」 的部分變成

try 
{ 
    UpdateModel(dinner); 
    dinnerRepository.Save(); 
    return PartialView("PartialDetails", new { id=dinner.DinnerID }); 
} 

,但你會怎麼做對扣部分?

一個簡單的錯誤處理解決方案發回的錯誤會

catch(Exception ex) 
{ 
    Response.StatusCode = 500;     
    return Content("An Error occured."); 
    //throw ex; 
} 

,但不會通過內置MVC強勁的ModelState通過。我想到了一些選項,但我真的想要2件事:

  1. 我想要在jQuery的錯誤屬性中處理錯誤。
  2. 我想盡可能地使用內置的ASP.Net MVC驗證邏輯。

這可能嗎?如果不是,你知道什麼是最好的選擇?

非常感謝。

更新 我還沒有把這個標記爲答案,因爲我還沒有實現我認爲最好的方法。

我已經決定,我不是真的很喜歡成功=>發送刷新列表,失敗=>發送錯誤消息的方法,我正在採取。我這樣做是爲了減少通話次數,但是刷新的列表確實正在設置到頁面上。試圖將兩者都緊緊地綁定到其整個頁面。

我打算添加一個自定義jQuery事件,當對話框關閉時刷新主頁面列表。實質上,它是觀察者模式。我喜歡頁面對彈出窗口「在完成時告訴我」(又名關閉)的想法,而不必告訴彈出窗口的原因。它確實需要額外的電話,但我不認爲這是一個大問題。

我仍然不確定我喜歡/不喜歡服務器端驗證的效果如何,我正在考慮僅使用客戶端驗證。雖然服務器端驗證看起來像乾淨的分層,但它也有一些問題,其中包括:

1)它將質量檢查放在最後,而不是開始。與製造相類似的是一輛汽車在到達經銷商時進行測試,而不是在製造過程中的各個點。 2)違反了Ajax的意圖。 Ajax不僅僅是發送異步事件,它還關於只發送我需要的內容並僅接收我需要的內容。發送整個模型狀態以提供錯誤細節似乎不適用於Ajax。

什麼,我想這樣做是有客戶端只驗證,但該服務器的代碼和一個自定義的視圖模型可以用來告訴客戶如何動態創建的驗證規則。

我還懷疑IronRuby的像IronPython的或動態語言可以提供一個更優雅的方式來解決這些問題,但也可能是更長一點之前,我考慮這種可能性。

+0

嗯,我認爲這真的取決於場景,如果做2請求不是一個問題,我會去那。個人在客戶端使用JavaScript進行大量驗證並不是我喜歡的東西(我不知道爲什麼,但是我看到的js不像一些非常值得信任/安全/同樣實現的東西(在這個jquery中保存一天)),特別是因爲有時候你不能在客戶端做所有的驗證,你必須使用某種服務器端檢查,比如(這個實體已經存在於數據庫中?),並且支持js禁用的客戶端,但正如我在開始時所說的那樣取決於情況。 – JOBG 2010-01-28 18:17:08

+0

我同意你不能在客戶端做所有的驗證,它看起來像驗證框架似乎主要針對現場錯誤(太長,而不是日期等)。至少在我見過的例子中。當你檢查用戶輸入時,Javascript似乎是檢查的適當位置。 – John 2010-02-17 17:10:59

+0

我已經確定了關於撥打2個電話而不是一個電話的決定,因爲它會從該電話下方的頁面視圖中取消部分視圖的詳細信息。我希望彈出窗口回到頁面視圖「我已關閉」,但不知道頁面視圖將執行什麼操作。 jQuery應該儘可能地做到這一點。這使我不必擔心對細節部分視圖的更改會影響頁面,反之亦然。 – John 2010-02-17 17:20:24

回答

4

如果我理解正確的是你正在嘗試做的,我的第一個答案是否定的,因爲它是通過和Ajax請求時不能使用模型的狀態。 也許你可以模仿的ModelState行爲,顯示錯誤:

  1. 傳遞一個List<KeyValuePair<string,string>>(屬性,消息)通過JSON(這將要求您通過modelErrors形成的ModelState到新的結構),做JS/jQuery驗證摘要的HTML構造(我認爲這是過度殺死解決方案)。

  2. 如果你要去服務器,並且出現任何錯誤,只需執行Html.ValidationSummary()的渲染部分,請將其傳遞給JSON並將其前置到表單中。如果一切正常,只需返回PartialDetails視圖並替換實際內容即可。這將需要某種狀態參數,以便您知道從ajax回調服務器返回的內容。

編輯:最後一個選項聽起來不錯,但棘手的,因爲你需要通過JSONResult一個字符串形式返回的局部視圖,這裏是一個關於破解Render a view as a string問題的解決方案。

就個人而言,我不認爲使用錯誤屬性將沒有任何好處可言,我只是用它來非常特殊的情況一樣超時錯誤,並且服務器異常,不應用例外。

編輯: 使用JSON

[AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult Edit(int id, FormCollection formValues) 
     { 
      Dinner dinner = dinnerRepository.GetDinner(id); 
      try 
      { 
       UpdateModel(dinner); 
       dinnerRepository.Save(); 
       return Json(new 
       { 
        result = "success", 
        html = this.RenderToString("PartialDetails", dinner) 
       }); 

      } 
      catch 
      { 
       foreach (var issue in dinner.GetRuleViolations()) 
       { 
        ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage); 
       } 
       return Json(new 
       { 
        result = "failed", 
        html = this.RenderToString("PartialEdit", dinner) 
       }); 
      } 
     } 

這裏的結果參數將讓你知道在每種情況下做什麼動作,只是要檢查它的回調。

+0

謝謝。但是,挑戰的一部分是,我真的希望將結果作爲PartialView結果返回,而不是作爲JSON結果。 2,你打2個電話嗎?一個返回成功/錯誤,另一個提供結果?這是我想到的一個選擇。 – John 2009-12-10 22:21:23

+0

它真的有一個像{「status」:[{「code」:「error」}],「html」:[{「html」:「很多html」}]}這樣的結構調用。如果您希望它只是一個partialView結果對象,那麼爲什麼不只是返回孔編輯部分視圖,以防模型出現錯誤?和詳細的部分視圖,當沒有錯誤發生時,模型狀態將以沒有問題的方式工作。 – JOBG 2009-12-11 00:43:06

+0

使我的場景與大多數示例不同的部分是,我想根據它是成功還是錯誤來執行兩種截然不同的操作。如果這是一個錯誤,我可以返回編輯部分視圖並重新創建對話框。但是,如果成功,我想關閉對話框並刷新主頁上的列表。因此,客戶端代碼需要知道是否成功/失敗,以便知道要更新哪個對象 - 對話框或列表。 – John 2009-12-11 14:11:41

2

添加我最喜歡的方法與MVC3。使用您的編輯方法,你可以不喜歡

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id, FormCollection formValues) 
{ 
    Dinner dinner = dinnerRepository.GetDinner(id); 
    try 
    { 
     UpdateModel(dinner); 
     dinnerRepository.Save(); 
     return Json (new { Success = true, Url = Url.Action("DetailsPartial", dinner), Div = "#DivToUpdateId" }); 
    } 
    catch 
    { 
     foreach (var issue in dinner.GetRuleViolations()) { 
     ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage); 
    } 
     //I am replacing this with a partial view which will contain the model state errors. For people using MVC 3 with razor they should be able to use their normal views as partials 
     return PartialView(dinner); 
    } 
} 

,然後你可以使用一個成功的功能像

success: function(data) { 
    if (data.Success) { 
     $.post(data.Url, function(partial) { 
      $(data.Div).html(partial); 
     }); 
    } 
    else 
    { 
     $('#formDiv').html(data) 
    } 
} 

所以基本上,如果結果的Json然後data.Success是真實的。然後使用Url中指定的動作的結果更新在json(data.Div)中指定的div。如果結果不是Json它,因爲post方法失敗並且formDiv用包含ModelState Errors的部分表單更新。這是我用於對話框的方法,但效果很好。很顯然,在MVC3中,我會改變一些編輯方法,如使用TryUpdateModel等,但只是試圖舉一個我的方法的例子。通過傳遞url併發布方法的結果,不需要嘗試將html呈現爲字符串以傳遞部分內容。

+0

有趣。你能夠發佈編輯PartialView的代碼嗎? – John 2012-04-23 14:57:40

相關問題