2012-10-29 31 views
6

Tôi đang làm việc trên một dự án được viết trên mvc 4 có một số trường hợp hành vi giống như thuật sĩ - một chuỗi các khung nhìn có cùng một mô hình bán đầy. Bắt đầu từ các điều khiển chế độ xem thứ hai ban đầu được hiển thị là không hợp lệ (là mô hình lô-gic, được chuyển đến phương thức bộ điều khiển có các thuộc tính tương ứng trống). Hiện tại, giải pháp ModelState.Clear(); được sử dụng, nhưng đặt nó vào từng phương pháp với mô hình làm đối số có vẻ xấu xí. Cùng với cách tiếp cận được tìm thấy tại đây Disable Model Validation in Asp.Net MVCLàm thế nào để vô hiệu hóa xác thực mô hình MVC 4?

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder(); 

Dự án có quá nhiều (trên 100) lớp mô hình để đăng ký từng người theo cách thủ công.

Có cách nào đơn giản hơn (có thể là khóa trong .config) để tắt hoàn toàn xác thực mô hình không?

+3

Cá nhân, tôi nghĩ rằng tôi muốn sử dụng một ViewModel khác nhau cho mỗi bước wizard. Điều này sẽ cho phép bạn sử dụng xác nhận nơi bạn cần nó (tức là trên các giá trị từ bước thủ thuật hiện tại!). –

Trả lời

8

Tôi không biết nó có thể làm việc này nhưng bạn đã thử này (mã bootstrap hoặc global.asax)

ModelValidatorProviders.Providers.Clear(); 
+0

Tôi đã kiểm tra. Mã này hoạt động. Trong dự án của tôi, tôi không thể sử dụng nó vì Validators được tạo bởi 'DataAnnotationsModelValidatorProvider' từ bộ sưu tập đã xóa đã được sử dụng để lấy ErrorMessages cho trình xác thực phía máy khách (thay vì mặc định" * "). Nhưng đây là câu trả lời đơn giản nhất cho câu hỏi của tôi. – user1782982

+0

Điều này không hiệu quả đối với tôi và tôi không hiểu tại sao –

2

Tôi không biết về tất cả tùy chọn trong web.config hoặc một cái gì đó tương tự. Nhưng bạn có thể sử dụng này:

Assembly.GetExecutingAssembly() 
    .GetTypes() 
    .Where(t => t.IsClass && t.Namespace == "Your.Name.Space") 
    .ToList() 
    .ForEach(t => ModelBinders.Binders[t] = new NonValidatingModelBinder()); 

Hoặc

typeof(MyModelType) 
    .Assembly 
    .GetTypes() 
    .Where(t => t.IsClass && t.Namespace == "Your.Name.Space") 
    .ToList() 
    .ForEach(t => ModelBinders.Binders[t] = new NonValidatingModelBinder()); 

Or Remove phần && t.Namespace == "Your.Name.Space" vì vậy nó sẽ thêm tất cả các lớp trong lắp ráp của bạn để NonValidatingModelBinder.

Đừng quên để thêm using System.Linq;

4

Tôi biết nó không thực sự trả lời câu hỏi của bạn, nhưng chỉ để mở rộng nhận xét của tôi: -

có vẻ như bạn có một cái gì đó như: -

public class MyModel 
{ 
    [Required] 
    public string Foo { get; set; } // Populated in step 1 
    [Required] 
    public string Bar { get; set; } // Populated in step 2 
} 

Bạn gặp sự cố khi bạn BÀI ĐĂNG bước 1 vì người dùng chưa nhập giá trị cho Bar, vì vậy, có ModelStateError.

giải pháp ưa thích của tôi, chứ không phải cố gắng để mess xung quanh với xác nhận của mô hình kiên trì của bạn, sẽ được tách Xem thực hiện của bạn từ việc thực hiện mô hình của bạn với một ViewModel cho mỗi bước Wizard, ví dụ: -

public class MyModel 
{ 
    [Required] 
    public string Foo { get; set; } 
    [Required] 
    public string Bar { get; set; } 
} 

public class StepOneModel 
{ 
    [Required] 
    public string Foo { get; set; } 
} 

public class StepTwoModel 
{ 
    // This really depends on the behaviour you want. 
    // In this example, the model isn't persisted until 
    // the last step, but you could equally well persist 
    // the partial model server-side and just include a 
    // key in subsequent wizard steps. 
    [Required] 
    public StepOneModel StepOne { get; set; } 

    [Required] 
    public string Bar { get; set; } 
} 

hành động điều khiển của bạn trông giống như sau: -

public ActionResult StepOne() 
{ 
    return View(new StepOneViewModel()); 
} 
[HttpPost] 
public ActionResult StepOne(StepOneViewModel model) 
{ 
    if(ModelState.IsValid) 
    { 
    var stepTwoModel = new StepTwoViewModel() 
    { 
     StepOne = model 
    }; 

    // Again, there's a bunch of different ways 
    // you can handle flow between steps, just 
    // doing it simply here to give an example 
    return View("StepTwo", model); 
    } 

    return View(model); 
} 
[HttpPost] 
public ActionResult StepTwo(StepTwoViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 
    // You could also add a method to the final ViewModel 
    // to do this mapping, or use something like AutoMapper 
    MyModel model = new MyModel() 
    { 
     Foo = model.StepOne.Foo 
     Bar = model.Bar 
    }; 

    this.Context.MyModels.Add(model); 
    this.Context.SaveChanges(); 
    } 

    return View(model); 
} 

xem StepOne của bạn trông giống như sau: -

@model StepOneModel 
@using (html.BeginForm()) { 
    @html.EditorFor(x => x.Foo); 
} 

xem StepTwo của bạn trông giống như sau: -

@model StepTwoModel 
@using (html.BeginForm("StepTwo")) { 
    @html.HiddenFor(x => x.StepOne); 
    @html.EditorFor(x => x.Bar); 
} 

Ưu điểm lớn so với chỉ tắt mô hình xác nhận là bạn có thể đặt các yêu cầu xác nhận cho bước hiện hành về ViewModel của bạn - bạn có thể đảm bảo rằng tất cả các các giá trị từ bước một là hợp lệ trước khi tiến hành bước hai.

  • Nếu bạn muốn có một cách tiếp cận RESTful hơn (nơi điều khiển của bạn không quan tâm rằng dữ liệu đến từ một cái nhìn kiểu wizard) một giải pháp phổ biến là để bọc từng bước trong một <div> client-side và sử dụng javascript để ẩn/hiển thị chúng khi người dùng tiến hành.

  • Nếu mô hình của bạn cần được duy trì giữa các bước, bạn sẽ cần phải suy nghĩ về ValidationAttributes trên mô hình của mình và ý nghĩa của chúng. Nếu bạn đã chú thích User.DateOfBirth với Required, nhưng bạn cần có khả năng tồn tại trước khi bước được điền, thì trên thực tế, User.DateOfBirthkhông phải là yêu cầu (ví dụ: EF CodeFirst không thể tạo cột NOT NULL vì chúng tôi cần để có thể duy trì giá trị null trong thời gian chờ đợi). Bạn cần thực hiện một số xác thực có điều kiện (ví dụ: IValidatableObject, MvcFoolproof, Fluent Validation) để xác thực mô hình hoàn chỉnh của bạn sau này.

+0

+1 iain - tóm tắt thú vị :) –

0
@{ 
HtmlHelper.ClientValidationEnabled = false; 
} 
Các vấn đề liên quan