代码之家  ›  专栏  ›  技术社区  ›  zerkms

在MVC 2中处理和验证Post数据的现代方法

  •  2
  • zerkms  · 技术社区  · 16 年前

    有很多文章专门讨论MVC中的数据,而没有关于MVC 2的内容。

    所以我的问题是:处理后查询并验证它的正确方法是什么?

    假设我们有两个动作。它们都在同一个实体上运行,但每个操作都有自己独立的对象属性集,这些属性应以自动方式绑定。例如:

    • 操作“a”应仅绑定对象的“name”属性,从post请求中获取。
    • 操作“b”应仅绑定对象的“日期”属性,从post请求中获取。

    据我所知,在这种情况下我们不能使用bind属性。

    那么,MVC2中处理POST数据并可能对其进行验证的最佳实践是什么?

    UPD :
    在执行操作之后-额外的逻辑将应用于对象,以便它们变得有效并准备存储在持久层中。对于操作“A”-它将设置最新到当前日期。

    2 回复  |  直到 16 年前
        1
  •  3
  •   Richard Szalay    16 年前

    我个人不喜欢使用域模型类作为我的视图模型。我发现它会导致验证、格式化方面的问题,并且通常感觉是错误的。事实上,我不会使用 DateTime 我的视图模型上的属性(我将在控制器中将其格式化为字符串)。

    我将使用两个单独的视图模型,每个模型都具有验证属性,作为主视图模型的属性公开:

    注意:我留下了如何将已发布的视图模型与主视图模型结合起来作为练习,因为有几种方法可以接近它。

    public class ActionAViewModel
    {
        [Required(ErrorMessage="Please enter your name")]
        public string Name { get; set; }
    }
    
    public class ActionBViewModel
    {
        [Required(ErrorMessage="Please enter your date")]
        // You could use a regex or custom attribute to do date validation,
        // allowing you to have a custom error message for badly formatted
        // dates
        public string Date { get; set; }
    }
    
    public class PageViewModel
    {
        public ActionAViewModel ActionA { get; set; }
        public ActionBViewModel ActionB { get; set; }
    }
    
    public class PageController
    {
        public ActionResult Index()
        {
            var viewModel = new PageViewModel
            {
                ActionA = new ActionAViewModel { Name = "Test" }
                ActionB = new ActionBViewModel { Date = DateTime.Today.ToString(); }
            };
    
            return View(viewModel);
        }
    
        // The [Bind] prefix is there for when you use 
        // <%= Html.TextBoxFor(x => x.ActionA.Name) %>
        public ActionResult ActionA(
            [Bind(Prefix="ActionA")] ActionAViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                // Load model, update the Name, and commit the change
            }
            else
            {
                // Display Index with viewModel
                // and default ActionBViewModel
            }
        }
    
        public ActionResult ActionB(
            [Bind(Prefix="ActionB")] ActionBViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                // Load model, update the Date, and commit the change
            }
            else
            {
                // Display Index with viewModel
                // and default ActionAViewModel
            }
        }
    }
    
        2
  •  2
  •   goldenelf2    16 年前

    处理发布数据和添加验证的一种可能方法是使用自定义模型绑定器。 以下是我最近用于向表单后数据添加自定义验证的小示例:

    public class Customer
    {
        public string Name { get; set; }
        public DateTime Date { get; set; }
    }
    
    
    public class PageController : Controller
    {
        [HttpPost]
        public ActionResult ActionA(Customer customer)
        {
            if(ModelState.IsValid) {
            //do something with the customer
            }
        }
    
        [HttpPost]
        public ActionResult ActionB(Customer customer)
        {
           if(ModelState.IsValid) { 
           //do something with the customer
           }
        }
    }
    

    CustomerModelBinder将是这样的:

        public class CustomerModelBinder : DefaultModelBinder
    {
        protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
        {
            if (propertyDescriptor.Name == "Name") //or date or whatever else you want
            {
    
    
                //Access your Name property with valueprovider and do some magic before you bind it to the model.
                //To add validation errors do (simple stuff)
                if(string.IsNullOrEmpty(bindingContext.ValueProvider.GetValue("Name").AttemptedValue))
                    bindingContext.ModelState.AddModelError("Name", "Please enter a valid name");
    
                //Any complex validation
            }
            else
            {
                //call the usual binder otherwise. I noticed that in this way you can use DataAnnotations as well.
                base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
            }
        }
    

    在global.asax中

    ModelBinders.Binders.Add(typeof(Customer), new CustomerModelBinder());
    

    如果您不想在调用actionb时绑定name属性(just date),那么只需再创建一个自定义模型绑定器,在“if”语句中,put返回空值、已经存在的值或您想要的任何值。然后在控制器中输入:

    [HttpPost]
    public ActionResult([ModelBinder(typeof(CustomerAModelBinder))] Customer customer)
    
    [HttpPost]
    public ActionResult([ModelBinder(typeof(CustomerBModelBinder))] Customer customer)
    

    其中,customerModelBinder将仅绑定名称,customerModelBinder将仅绑定日期。

    这是我发现的验证模型绑定的最简单的方法,并且我在复杂的视图模型中获得了一些非常酷的结果。我敢打赌我错过了一些事情,也许一个更专业的人能回答。 希望我答对了你的问题……:)

    推荐文章