ASP.Net MVC 控制器从 Uri 到模型 - 我们可以定义顺序吗?

ASP.Net MVC Controller FromUri to Model - Can we define the order?

在我的申请中,我通过查询字符串提供参数来浏览到 URL。根据 URI,触发相应控制器的操作,并将提供的参数自动映射到我的模型。

URL: http://{host}:{port}/{website}/{controller}/{action}?{querystring}

URI: /{controller}/{Action}?{QueryString}

My URI: Employee/Add?EmployeeCode=Code3&EmployeeId=103

雇员模型

public class EmployeeModel
{
        public Employee()
        {
        }

        public string EmployeeId { get; set; }

        public string EmployeeCode { get; set; }

        //Some more properties here
}

员工控制人

[HttpGet]
[Route("Add")]
public IActionResult Add([FromUri] EmployeeModel model)
{
        //Some code here
}

虽然这一切都很棒,但当我浏览时,下面是断点命中的顺序,

  1. Add EmployeeController
  2. 方法
  3. EmployeeModel
  4. 的默认 构造函数
  5. EmployeeModel
  6. EmployeeId属性 的设置方法
  7. EmployeeModel
  8. EmployeeCode属性的设置方法

我怀疑属性初始化的顺序是基于它们在 class 中声明的顺序。

但是,要创建实例并初始化框架必须使用反射的属性。根据 Type.GetProperties 的 MSDN 文档,订单未得到保证。

The GetProperties method does not return properties in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which properties are returned, because that order varies.

我基本上希望初始化按特定顺序进行,这可能吗?

您无法让模型绑定机制按特定顺序执行操作,但您可以确保在必须的位置应用该顺序。

据推测,EmployeeModel 是一个域模型对象,其顺序实际上很重要,您现在模型直接绑定到该类型。相反,引入一个 edit model1 模型绑定到,然后 map 到你的模型类型:

public class EmployeeEditModel
{
    public string EmployeeId { get; set; }
    public string EmployeeCode { get; set; }
}

// and change your action signature to this:
[HttpGet]
[Route("Add")]
public IActionResult Add([FromUri] EmployeeEditModel model)

1 有关 编辑模型 的解释,请参阅 this old answer of mine.[=19 的最后评论=]


要执行映射,您有多种选择,有些比其他的更好。选择一个适合你的 - 然而,由于顺序很重要的原因可能是域模型对象中固有的东西,我建议你将逻辑放在其中(例如在构造函数中),以便更容易记住更改如果要求发生变化。

  • 通过模型对象上的构造函数进行映射

    public class EmployeeModel
    {
        public EmployeeModel(string employeeId, string employeeCode /* , ... */)
        {
            // do stuff in whatever order you need
            EmployeeId = employeeId;
            EmployeeCode = employeeCode;
        }
    
        // Now your properties can be get-only
        public string EmployeeId { get; }
        public string EmployeeCode { get; }
    }
    
  • 通过按正确顺序执行所有操作的扩展方法进行映射

    public static class EmployeeEditModelExtensions
    {
        public EmployeeModel AsDomainModel(this EmployeeEditModel editModel)
        {
            // do stuff in whatever order you need
            var model = new EmployeeModel();
            model.EmployeeId = editModel.EmployeeId;
            model.EmployeeCode = editModel.EmployeeCode;
            // ...
        }
    
        // Now your properties can be get-only
        public string EmployeeId { get; }
        public string EmployeeCode { get; }
    }
    
  • 使用外部框架,例如 AutoMapper,通过自定义配置确保顺序正确

  • 做点别的。唯一的目的是让您从 EmployeeEditModel 实例到 EmployeeModel 实例,以正确的顺序分配给 EmployeeModel 的属性。由于这段代码是你自己写的,所以你可以为所欲为。