2011-10-29 27 views

Trả lời

7

Thông thường bạn chỉ chuyển hướng sau bài đăng thành công (không có lỗi Xác thực mẫu), nếu không bạn sẽ gửi lại trang có thông báo lỗi xác thực.

Các redirect trong mẫu PRG ngăn đôi niêm yết, do đó không có hại cho gửi lại cùng một trang (+ thông báo lỗi) vì bài đã không thành công và sẽ không được trừ khi một cái gì đó thay đổi để làm xác nhận qua.

Sửa:

Dường như bạn đang tìm kiếm thông qua ModelState để yêu cầu (chuyển hướng) bên cạnh. Điều này có thể được thực hiện bằng cách sử dụng TempData để lưu trữ ModelState tối đa yêu cầu tiếp theo. FYI, TempData sử dụng Phiên.

Điều này có thể được triển khai với ActionFilters. Ví dụ có thể được tìm thấy trong các mã dự án MvcContrib: ModelStateToTempDataAttribute

này cũng đã được nhắc đến cùng với mẹo khác trong bài viết một 'thực hành tốt nhất' trên weblogs.asp.net (dường như tác giả đã chuyển blog, nhưng tôi không thể tìm thấy bài viết này trên blog mới). Từ bài viết:

Một trong những vấn đề với mẫu này là khi xác thực không thành công hoặc bất kỳ ngoại lệ nào xảy ra, bạn phải sao chép ModelState vào TempData. Nếu bạn đang làm nó bằng tay, hãy dừng lại nó, bạn có thể làm điều này tự động với lọc hành động, như sau:

khiển

[AcceptVerbs(HttpVerbs.Get), OutputCache(CacheProfile = "Dashboard"), StoryListFilter, ImportModelStateFromTempData] 
public ActionResult Dashboard(string userName, StoryListTab tab, OrderBy orderBy, int? page) 
{ 
    //Other Codes 
    return View(); 
} 

[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData] 
public ActionResult Submit(string userName, string url) 
{ 
    if (ValidateSubmit(url)) 
    { 
     try 
     { 
      _storyService.Submit(userName, url); 
     } 
     catch (Exception e) 
     { 
      ModelState.AddModelError(ModelStateException, e); 
     } 
    } 

    return Redirect(Url.Dashboard()); 
} 

lọc hành động

public abstract class ModelStateTempDataTransfer : ActionFilterAttribute 
{ 
    protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName; 
} 

public class ExportModelStateToTempData : ModelStateTempDataTransfer 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     //Only export when ModelState is not valid 
     if (!filterContext.Controller.ViewData.ModelState.IsValid) 
     { 
      //Export if we are redirecting 
      if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult)) 
      { 
       filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState; 
      } 
     } 

     base.OnActionExecuted(filterContext); 
    } 
} 

public class ImportModelStateFromTempData : ModelStateTempDataTransfer 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary; 

     if (modelState != null) 
     { 
      //Only Import if we are viewing 
      if (filterContext.Result is ViewResult) 
      { 
       filterContext.Controller.ViewData.ModelState.Merge(modelState); 
      } 
      else 
      { 
       //Otherwise remove it. 
       filterContext.Controller.TempData.Remove(Key); 
      } 
     } 

     base.OnActionExecuted(filterContext); 
    } 
} 
+2

Điều đó không đúng. Có nhiều tác hại ... tất cả POST phải được theo sau bởi chuyển hướng. (1) Đây là cách duy nhất để xóa yêu cầu POST khỏi lịch sử trình duyệt (2) Nếu không, người dùng nhấn BACK hoặc REFRESH sẽ nhận được xác nhận "gửi lại" gây nhầm lẫn và khó chịu (3) Người dùng chọn "gửi lại" sẽ không biết cách kết quả cuối cùng của hành động có thể là! Đây là một dấu hiệu của các ứng dụng web chất lượng chuyên nghiệp trong hơn 15 năm. (Không phổ biến trong ASP hoặc ASP.NET ứng dụng web mặc dù) Hơn nữa ngay cả một GET * cố gắng * một thay đổi trạng thái không lặp lại nên được chuyển hướng. – Jack

+0

Quan điểm của tôi đơn giản là nếu Xác thực mẫu không thành công, trạng thái máy chủ không được thay đổi và do đó ngay cả khi yêu cầu POST giống nhau được gửi lại, trạng thái máy chủ vẫn không thay đổi.Nhưng nếu bạn cảm thấy mạnh mẽ về việc ngăn chặn xác nhận gửi lại phiền toái cho trường hợp cụ thể này (POST không thành công mà không có thay đổi trạng thái máy chủ), tại sao bạn không chuyển hướng đơn giản? Có thể bạn sẽ cần một phiên làm việc (ví dụ: TempData) để thực hiện ít nhất thông báo lỗi xác thực cho yêu cầu được chuyển hướng và thông báo cho người dùng tại sao POST không thành công. Nhưng sau đó một lần nữa, hiển thị trạng thái phiên trong một yêu cầu GET không phải là rất RESTful ... – marapet

+0

"trạng thái máy chủ không thay đổi" // yêu cầu này không phải là, nhưng bạn giả định rằng thời gian tới nó cũng sẽ không bị thay đổi// bạn không thể đưa ra giả thiết // đó cũng chỉ là một phần của vấn đề // và việc đánh dấu trùng lặp phải được thực hiện phía máy chủ để mạnh mẽ // "đơn giản là chuyển hướng" làm cách nào để truy cập vào ModelState theo yêu cầu tiếp theo? – Jack

0

gì ý của bạn là chuyển hướng "bắt buộc"? Thường thì chúng ta sử dụng try/catch trong controller, nếu thử thành công, bạn có thể chuyển hướng đến View (nếu bạn CẦN) hoặc cũng có thể trả về bất kỳ view nào, hoặc bất cứ thứ gì bạn cần. Việc nắm bắt thường tái hiển thị trang gốc với thông báo lỗi vì yêu cầu đăng bài không thành công.

Hy vọng tôi không hiểu lầm bạn :)

+0

"bắt buộc" cho các ứng dụng web chuyên nghiệp - hãy kiểm tra với người chơi - xem cách Google hoặc IBM hoặc PayPal hoặc EBay làm điều đó ... rất hiếm khi ứng dụng web ASP hoặc ASP.NET triển khai chính xác vì Microsoft không bao giờ hiển thị kỹ thuật trong ví dụ (họ không muốn gây nhầm lẫn cho mọi người) – Jack

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