2009-12-10 41 views
9

Đây là lần theo dõi previous question mà tôi đã có trước đây về việc truyền lại lỗi cho khách hàng, nhưng cũng liên quan đến ModelState.Trong ASP.Net MVC, ModelState có thể được sử dụng với bản cập nhật ajax không?

Có ai thành công sử dụng phương pháp tiếp cận bữa tối Nerd hay không, nhưng với Ajax? Vì vậy, Nerd Dinner thực hiện cập nhật như vậy.

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

Sử dụng jQuery $ .ajax

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

Ajax, "thử" một phần của bộ điều khiển trở nên

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

, nhưng bạn sẽ làm gì về phần bắt?

Một giải pháp xử lý lỗi đơn giản để gửi lại một lỗi sẽ

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

, nhưng điều đó không vượt qua qua ModelState mạnh mẽ được xây dựng vào MVC. Tôi đã nghĩ đến một số tùy chọn, nhưng tôi thực sự muốn 2 điều:

  1. Tôi muốn lỗi được xử lý trong thuộc tính lỗi của jQuery.
  2. Tôi muốn sử dụng được xây dựng trong logic xác thực ASP.Net MVC càng nhiều càng tốt.

Điều này có khả thi không? Nếu không, lựa chọn thay thế tốt nhất mà bạn biết là gì?

Rất cám ơn.

Cập nhật Tôi chưa đánh dấu câu trả lời này vì tôi chưa triển khai những gì tôi nghĩ sẽ hoạt động tốt nhất.

Tôi đã quyết định rằng tôi không thực sự thích thành công => gửi danh sách làm mới, thất bại => gửi thông báo lỗi mà tôi đang dùng. Tôi đã làm điều này để giảm số lượng cuộc gọi, nhưng danh sách được làm mới thực sự được đặt thành trang. Cố gắng thực hiện cả hai liên kết chặt chẽ popup với trang tổng thể của nó.

Tôi sẽ thêm một sự kiện jQuery tùy chỉnh làm mới danh sách trang chính khi hộp thoại đóng. Về bản chất, đó là mẫu người quan sát. Tôi thích ý tưởng rằng trang nói đến cửa sổ bật lên "cho tôi biết khi nào bạn đã hoàn tất" (còn gọi là đóng), mà không cần phải thông báo lý do bật lên. Nó đòi hỏi một cuộc gọi bổ sung, nhưng tôi không thấy đó là một vấn đề lớn.

Tôi vẫn không chắc chắn mức độ mình thích/không thích xác thực phía máy chủ và tôi đang cân nhắc việc xác thực chỉ phía máy khách. Trong khi xác thực phía máy chủ có vẻ như phân lớp sạch, nó cũng có một số vấn đề, bao gồm:

1) Nó đặt kiểm tra chất lượng ở cuối, thay vì bắt đầu. Một sự tương tự với sản xuất sẽ là một chiếc xe được kiểm tra khi nó đến đại lý, thay vì tại các điểm trong quá trình nó được xây dựng.
2) Nó vi phạm mục đích của Ajax. Ajax không chỉ là về việc gửi các sự kiện không đồng bộ, nó còn chỉ gửi những gì tôi cần và chỉ nhận những gì tôi cần. Gửi trở lại toàn bộ mô hình để cung cấp các chi tiết lỗi dường như không đi với Ajax.Điều tôi đang nghĩ đến là chỉ thực hiện xác thực phía máy khách, nhưng mã máy chủ đó và mô hình chế độ xem tùy chỉnh có thể được sử dụng để cho khách hàng biết cách tự động tạo các quy tắc xác thực đó. Tôi cũng nghi ngờ rằng một ngôn ngữ động như IronRuby hoặc IronPython có thể cung cấp một cách thanh lịch hơn để giải quyết những vấn đề này, nhưng có thể lâu hơn một chút trước khi tôi nhìn vào khả năng đó.

+0

tôi cũng nghĩ rằng nó thực sự phụ thuộc vào kịch bản, nếu làm 2 yêu cầu không phải là một vấn đề tôi sẽ đi cho điều đó.Cá nhân làm rất nhiều xác nhận với JavaScript ở phía khách hàng không phải là thứ mà tôi yêu (tôi không biết tại sao, nhưng tôi thấy js giống như một thứ không đáng tin cậy/an toàn/thực hiện đều đặn (trong jquery này tiết kiệm trong ngày)), đặc biệt bởi vì đôi khi bạn không thể thực hiện tất cả các xác thực trên phía máy khách, bạn phải sử dụng một số loại kiểm tra bên, như (thực thể này đã tồn tại trong DB?) và hỗ trợ các ứng dụng khách đã tắt, nhưng như tôi đã nói lúc đầu phụ thuộc vào kịch bản. – JOBG

+0

Tôi đồng ý rằng bạn không thể thực hiện tất cả xác thực ở phía máy khách, có vẻ như khung xác thực có vẻ hướng chủ yếu vào các lỗi trường (quá dài, không phải ngày, v.v ...). Ít nhất trong các ví dụ mà tôi đã nhìn thấy. Khi bạn kiểm tra đầu vào của người dùng, Javascript có vẻ là nơi thích hợp để thực hiện việc kiểm tra. – John

+0

Tôi đã củng cố quyết định của mình về việc thực hiện 2 cuộc gọi, thay vì một, bởi vì nó tách các chi tiết một phần xem từ chế độ xem trang bên dưới nó. Tôi muốn cửa sổ bật lên nói lại chế độ xem trang "Tôi đã đóng" nhưng không biết bất kỳ điều gì về lượt xem trang sẽ thực hiện. jQuery nên làm cho điều đó có thể mà không cần nhiều nỗ lực. Điều đó cho phép tôi không lo lắng rằng những thay đổi đối với chi tiết từng phần của tôi sẽ ảnh hưởng đến trang và ngược lại. – John

Trả lời

4

Nếu tôi hiểu đúng những gì bạn đang cố gắng làm, câu trả lời đầu tiên của tôi sẽ không có, bạn không thể sử dụng trạng thái mô hình khi nó thông qua và yêu cầu Ajax. lẽ bạn có thể bắt chước các hành vi ModelState, để hiển thị lỗi:

  1. Đi qua một List<KeyValuePair<string,string>> (bất động sản, tin nhắn) bằng JSON (điều này sẽ yêu cầu bạn phải vượt qua modelErrors hình thành ModelState sang cơ cấu mới) và làm việc xây dựng HTML của một bản tóm tắt xác nhận bởi JS/jQuery (mà tôi nghĩ là qua giải pháp diệt).

  2. Nếu bạn định truy cập máy chủ và có bất kỳ lỗi nào, hãy thực hiện một phần hiển thị của Html.ValidationSummary(), chuyển nó qua JSON và thêm nó vào biểu mẫu. Nếu mọi thứ đều ổn, chỉ cần trả lại chế độ xem PartialDetails và thay thế nội dung thực tế. Điều này sẽ yêu cầu một số loại tham số trạng thái để bạn biết những gì đang trở lại từ máy chủ trên gọi lại ajax.

EDIT: Tùy chọn cuối cùng này nghe có vẻ tốt nhưng khó khăn, bởi vì bạn sẽ cần phải trả lại một phần Xem ở dạng chuỗi bằng cách JsonResult, đây là một câu hỏi và giải pháp về hack Render a view as a string.

Cá nhân, tôi không nghĩ rằng việc sử dụng thuộc tính lỗi sẽ làm bất kỳ điều gì tốt, tôi chỉ sử dụng nó cho các tình huống rất cụ thể như lỗi hết thời gian chờ và ngoại lệ máy chủ chứ không phải ngoại lệ cho ứng dụng.

EDIT: Sử dụng 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) 
       }); 
      } 
     } 

Ở đây, tham số kết quả sẽ cho bạn biết những hành động cần làm trong mỗi trường hợp, chỉ cần kiểm tra xem nó trên gọi lại.

+0

Cảm ơn. Tuy nhiên, một phần của thử thách là tôi thực sự muốn gửi kết quả trở lại dưới dạng kết quả PartialView chứ không phải là kết quả JSON. Đối với 2., bạn đang thực hiện 2 cuộc gọi? Một để trả về thành công/lỗi và một để cung cấp kết quả? Đó là một lựa chọn mà tôi đã nghĩ đến. – John

+0

Cuộc gọi thực sự của nó với cấu trúc này như {"trạng thái": [{"mã": "lỗi"}], "html": [{"html": "nhiều html"}]}. Nếu bạn muốn nó chỉ là một đối tượng ResultView Result, tại sao không chỉ trả về lỗ Edit partial view, trong trường hợp mô hình có lỗi? và Xem chi tiết một phần khi không có lỗi xảy ra, Trạng thái mô hình sẽ hoạt động mà không có vấn đề gì theo cách đó. – JOBG

+0

Phần khiến kịch bản của tôi khác với hầu hết các ví dụ là tôi muốn thực hiện hai hành động rất khác nhau dựa trên việc đó là một thành công hay sai sót. Nếu đó là lỗi, tôi có thể trả lại phần Chỉnh sửa một phần và tạo lại hộp thoại. Tuy nhiên, nếu đó là một thành công, tôi muốn đóng hộp thoại và làm mới danh sách trên trang chính. Vì vậy, mã phía máy khách cần biết nếu đó là một thành công/thất bại để biết đối tượng nào cần cập nhật - hộp thoại hoặc danh sách. – John

2

Thêm phương pháp ưa thích của tôi với MVC3. Sử dụng chỉnh sửa phương pháp của bạn, bạn có thể làm một cái gì đó giống như

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

và sau đó bạn có thể sử dụng một chức năng thành công như

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

nên về cơ bản, nếu kết quả là Json sau đó data.Success là đúng. Sau đó nó cập nhật div được chỉ định trong json (data.Div) với các kết quả của hành động được chỉ định trong Url. Nếu kết quả không phải là Json của nó bởi vì phương thức post không thành công và formDiv được cập nhật với biểu mẫu một phần có chứa lỗi ModelState. Đây là cách tiếp cận tôi sử dụng cho các hộp thoại nhưng nó hoạt động khá tốt. Rõ ràng với MVC3 tôi muốn thay đổi một số phương pháp chỉnh sửa như sử dụng TryUpdateModel vv, nhưng chỉ cố gắng đưa ra một ví dụ về cách tiếp cận của tôi. Bằng cách chuyển url và đăng kết quả của phương thức, không cần phải cố gắng hiển thị html thành chuỗi để truyền một phần.

+0

Thú vị. Bạn có thể đăng mã của mình cho Edit PartialView không? – John

Các vấn đề liên quan