Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 在MVC2中处理和验证POST数据的现代方法_Asp.net_Asp.net Mvc 2 - Fatal编程技术网

Asp.net 在MVC2中处理和验证POST数据的现代方法

Asp.net 在MVC2中处理和验证POST数据的现代方法,asp.net,asp.net-mvc-2,Asp.net,Asp.net Mvc 2,有很多文章致力于在MVC中处理数据,而没有关于MVC2的文章 所以我的问题是:处理POST查询并验证它的正确方法是什么 假设我们有两个动作。它们都在同一个实体上操作,但每个操作都有自己独立的对象属性集,应该以自动方式绑定这些属性。例如: 操作“A”应该只绑定对象的“Name”属性,该属性取自POST请求 操作“B”应仅绑定对象的“日期”属性,该属性取自POST请求 据我所知,在这种情况下我们不能使用Bind属性 那么,MVC2中处理POST数据并可能验证它的最佳实践是什么 UPD: 在执行操

有很多文章致力于在MVC中处理数据,而没有关于MVC2的文章

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

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

  • 操作“A”应该只绑定对象的“Name”属性,该属性取自POST请求
  • 操作“B”应仅绑定对象的“日期”属性,该属性取自POST请求
据我所知,在这种情况下我们不能使用Bind属性

那么,MVC2中处理POST数据并可能验证它的最佳实践是什么

UPD

在执行操作后-附加逻辑将应用于对象,以便它们变得有效并准备存储在持久层中。对于操作“A”-将日期设置为当前日期。

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

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

注意:我将如何将发布的视图模型与主视图模型结合起来作为练习留给您,因为有几种方法可以实现它

公共类ActionAViewModel
{
[必需(ErrorMessage=“请输入您的姓名”)]
公共字符串名称{get;set;}
}
公共类ActionBViewModel
{
[必需(ErrorMessage=“请输入您的日期”)]
//可以使用正则表达式或自定义属性进行日期验证,
//允许您为格式不正确的用户自定义错误消息
//日期
公共字符串日期{get;set;}
}
公共类页面视图模型
{
公共ActionAViewModel ActionA{get;set;}
public ActionBViewModel ActionB{get;set;}
}
公共类页面控制器
{
公共行动结果索引()
{
var viewModel=新页面视图模型
{
ActionA=新ActionAViewModel{Name=“Test”}
ActionB=new ActionBViewModel{Date=DateTime.Today.ToString();}
};
返回视图(viewModel);
}
//[Bind]前缀是在您使用时使用的
//x.A.名称)%%>
公共行动结果行动(
[Bind(Prefix=“ActionA”)]ActionAViewModel视图模型
{
if(ModelState.IsValid)
{
//加载模型、更新名称并提交更改
}
其他的
{
//使用viewModel显示索引
//和默认操作bviewmodel
}
}
公共行动结果行动B(
[Bind(Prefix=“ActionB”)]ActionBViewModel视图模型
{
if(ModelState.IsValid)
{
//加载模型、更新日期并提交更改
}
其他的
{
//使用viewModel显示索引
//和默认的ActionAViewModel
}
}
}

处理POST数据和添加验证的一种可能方法是使用自定义模型活页夹。 下面是我最近用来向POST表单数据添加自定义验证的一个小示例:

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属性(只是日期),那么只需再创建一个自定义模型绑定器,并在“If”语句中,将其设置为返回null或已存在的值,或任何您想要的值。然后在控制器中放入:

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

[HttpPost]
public ActionResult([ModelBinder(typeof(CustomerBModelBinder))] Customer customer)
其中CustomerModelBinder将仅绑定名称,CustomerModelBinder将仅绑定日期

这是我发现的最简单的验证模型绑定的方法,我已经在复杂视图模型中获得了一些非常酷的结果。我敢打赌,我错过了一些东西,也许一个更专业的人可以回答。
希望我没有弄错你的问题…:)

给定类Employee{string Name{get;set;}Datetime?Date{get;set;}},动作A中的Employee实例将包含什么?你说它应该只绑定名字。它会有一个空的日期吗?试图得到一个更好的画面。@Raje:没有。在Employee对象保存到持久性存储之前,将应用一些额外的逻辑(我将在几秒钟内更新问题以清除此问题),不确定您是否已经阅读了这篇优秀的文章:我没有。现在就做;-)非常感谢。但问题仍然悬而未决;-)我读过那篇文章。这很有趣,但与主题无关:-我需要一些时间来了解这段代码的功能。谢谢你的回答;-)那么-在现实生活中,您仍然在使用viewmodels中指定为属性的验证?我想将验证逻辑转移到服务应用程序级别,以分离业务逻辑。在这种情况下,我看不到任何进行验证的可能性,除了自定义if(…)elseif(…)等(在一些验证类中封装)之外,正如您可能已经发现的,验证系统是完全可插入的,因此您不需要使用属性。最主要的是分离视图模型,以充分利用模型绑定。另外,不要混淆输入验证和域验证。加载模型并更新日期后,您可以对模型运行自己的自定义验证逻辑,以检查无效的日期范围。例如,“验证系统完全可插入,因此您不需要使用属性。”--那么怎么做?是的,您答对了,但验证分为两部分:输入验证(当我们组合ViewModel时,您的示例中的客户)和业务逻辑验证(当我们检查数据是否符合应用程序强制要求时)看起来很奇怪,不是吗?我在解决方案中添加了更多内容。这很奇怪。在我看来,理想的方法是在一个位置进行验证,最好是
[HttpPost]
public ActionResult([ModelBinder(typeof(CustomerAModelBinder))] Customer customer)

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