asp.net-mvc – 自定义模型绑定,模型状态和数据注释

前端之家收集整理的这篇文章主要介绍了asp.net-mvc – 自定义模型绑定,模型状态和数据注释前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一些关于自定义模型绑定,模型状态和数据注释的问题.

1)如果我的模型上有数据注释,那么在自定义模型绑定器中进行验证是否是多余的,因为这就是我认为的数据注释点.

2)为什么我的控制器将模型状态视为有效,即使它不是,主要是我使Name属性为null或太短.

3)将自定义模型绑定器视为构造方法是否可行,因为这是他们提醒我的.

首先是我的模型.

  1. public class Projects
  2. {
  3. [Key]
  4. [required]
  5. public Guid ProjectGuid { get; set; }
  6.  
  7. [required]
  8. public string AccountName { get; set; }
  9.  
  10. [required(ErrorMessage = "Project name required")]
  11. [StringLength(128,ErrorMessage = "Project name cannot exceed 128 characters")]
  12. [MinLength(3,ErrorMessage = "Project name must be at least 3 characters")]
  13. public string Name { get; set; }
  14.  
  15. [required]
  16. public long TotalTime { get; set; }
  17. }

然后我使用自定义模型绑定器绑定模型的某些属性.请不要介意它只是试图让它运行然后重构它是快速和肮脏的.

  1. public class ProjectModelBinder : IModelBinder
  2. {
  3. public object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
  4. {
  5. if (controllerContext == null)
  6. {
  7. throw new ArgumentNullException("controllerContext");
  8. }
  9. if (bindingContext == null)
  10. {
  11. throw new ArgumentNullException("bindingContext");
  12. }
  13. var p = new Project();
  14. p.ProjectGuid = System.Guid.NewGuid();
  15. p.AccountName = controllerContext.HttpContext.User.Identity.Name;
  16. p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
  17. p.TotalTime = 0;
  18.  
  19. //
  20. // Is this redundant because of the data annotations?!?!
  21. //
  22. if (p.AccountName == null)
  23. bindingContext.ModelState.AddModelError("Name","Name is required");
  24.  
  25. if (p.AccountName.Length < 3)
  26. bindingContext.ModelState.AddModelError("Name","Minimum length is 3 characters");
  27.  
  28. if (p.AccountName.Length > 128)
  29. bindingContext.ModelState.AddModelError("Name","Maximum length is 128 characters");
  30.  
  31. return p;
  32. }
  33. }

现在我的控制器动作.

  1. [HttpPost]
  2. public ActionResult CreateProject([ModelBinder(typeof(ProjectModelBinder))]Project project)
  3. {
  4. //
  5. // For some reason the model state comes back as valid even when I force an error
  6. //
  7. if (!ModelState.IsValid)
  8. return Content(Boolean.FalseString);
  9.  
  10. //_projectRepository.CreateProject(project);
  11.  
  12. return Content(Boolean.TrueString);
  13.  
  14. }

编辑

我在另一个stackoverflow问题上找到了一些代码,但我不确定在哪个点上我会将以下值注入此possible solution.

创建新对象时我想要注入的内容

  1. var p = new Project();
  2. p.ProjectGuid = System.Guid.NewGuid();
  3. p.AccountName = controllerContext.HttpContext.User.Identity.Name;
  4. p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
  5. p.TotalTime = 0;

如何将上述代码纳入以下内容(可能的解决方案):

  1. public class ProjectModelBinder : DefaultModelBinder
  2. {
  3. public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
  4. {
  5. if (bindingContext.ModelType == typeof(Project))
  6. {
  7. ModelBindingContext newBindingContext = new ModelBindingContext()
  8. {
  9.  
  10. ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
  11. () => new Project(),// construct a Project object,typeof(Project) // using the Project Metadata
  12. ),ModelState = bindingContext.ModelState,ValueProvider = bindingContext.ValueProvider
  13.  
  14. };
  15.  
  16. // call the default model binder this new binding context
  17. return base.BindModel(controllerContext,newBindingContext);
  18. }
  19. else
  20. {
  21. return base.BindModel(controllerContext,bindingContext);
  22. }
  23. }
  24.  
  25. }
  26.  
  27. }

解决方法

如果从DefaultModelBinder继承,覆盖BindModel方法,调用base.BindModel方法然后进行手动更改(设置guid,帐户名和总时间),您会发现事情更容易.

1)完成验证是多余的.您可以编写代码来反映验证元数据,就像默认情况一样,或者只是删除数据注释验证,因为您没有在模型绑定器中使用它.

2)我不知道,似乎是正确的,您应该单步执行代码并确保自定义绑定器填充所有适用的规则.

3)这是一个肯定的工厂,但不是一个构造函数.

编辑:你不能更接近解决方案,只需在模型工厂函数中设置所需的属性

  1. public class ProjectModelBinder : DefaultModelBinder
  2. {
  3. public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
  4. {
  5. if (bindingContext.ModelType == typeof(Project))
  6. {
  7. ModelBindingContext newBindingContext = new ModelBindingContext()
  8. {
  9.  
  10. ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
  11. () => new Project() // construct a Project object
  12. {
  13. ProjectGuid = System.Guid.NewGuid(),AccountName = controllerContext.HttpContext.User.Identity.Name,// don't set name,thats the default binder's job
  14. TotalTime = 0,},typeof(Project) // using the Project Metadata
  15. ),ValueProvider = bindingContext.ValueProvider
  16.  
  17. };
  18.  
  19. // call the default model binder this new binding context
  20. return base.BindModel(controllerContext,newBindingContext);
  21. }
  22. else
  23. {
  24. return base.BindModel(controllerContext,bindingContext);
  25. }
  26. }
  27.  
  28. }

或者您可以替代地覆盖CreateModel方法

  1. protected override object CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,System.Type modelType)
  2. {
  3. if (modelType == typeof(Project))
  4. {
  5. Project model = new Project()
  6. {
  7. ProjectGuid = System.Guid.NewGuid(),thats the default binder's job
  8. TotalTime = 0,};
  9.  
  10. return model;
  11. }
  12.  
  13. throw new NotSupportedException("You can only use the ProjectModelBinder on parameters of type Project.");
  14. }

猜你在找的asp.Net相关文章