ASP.Net MVC控制器FromUri到Model - 我们可以定义订单吗?

时间:2016-08-23 06:06:08

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 automapper system.reflection

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

  

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

     

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

     

我的URI:员工/添加?EmployeeCode = Code3& EmployeeId = 103

EmployeeModel

public class EmployeeModel
{
        public Employee()
        {
        }

        public string EmployeeId { get; set; }

        public string EmployeeCode { get; set; }

        //Some more properties here
}

EmployeeController

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

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

  1. 添加 EmployeeController方法
  2. EmployeeModel的默认构造函数
  3. 设置EmployeeModel的 EmployeeId 属性的方法
  4. 设置EmployeeModel的 EmployeeCode 属性的方法
  5. 我怀疑属性初始化的顺序是基于它们在类中声明的顺序。

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

      

    GetProperties方法不返回特定属性   订单,例如字母或声明订单。你的代码一定不能   取决于返回属性的顺序,因为那样   订单各不相同。

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

1 个答案:

答案 0 :(得分:2)

您无法使用模型绑定机制按特定顺序执行操作,但可以确保将订单应用到必须的位置。

据推测,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 ,然后映射到您的模型类型:

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; }
}

1 有关编辑模型的说明,请参阅this old answer of mine的最终评论。

要执行映射,您有许多替代方案,有些方法比其他方案更好。选择一个适合你的 - 但是,由于订单重要的原因可能是域模型对象中固有的东西,我建议你把逻辑放在其中(例如在构造函数中),以便更容易记住如果要求发生变化,就改变它。

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

    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; }
    }
    
  • 通过扩展方法映射,以正确的顺序执行所有操作

    EmployeeEditModel
  • 使用AutoMapper等外部框架和自定义配置,以确保订购正确

  • 做点别的事。唯一的目的是让您从EmployeeModel实例转到EmployeeModel实例,以正确的顺序分配# DAS_AGENT uses PatternLayout. log4j.appender.DAS_AGENT.layout=org.wso2.carbon.analytics.shared.data.agents.log4j.util.TenantAwarePatternLayout log4j.appender.DAS_AGENT.columnList=%D,%S,%A,%d,%c,%p,%m,%H,%I,%Stacktrace log4j.appender.DAS_AGENT.userName=admin log4j.appender.DAS_AGENT.password=xxxxxxx log4j.appender.DAS_AGENT.url=tcp://localhost:7612 log4j.appender.DAS_AGENT.maxTolerableConsecutiveFailure=5 log4j.appender.DAS_AGENT.streamDef=loganalyzer:1.0.0 log4j.logger.trace.messages=TRACE,CARBON_TRACE_LOGFILE 的属性。由于您自己编写此代码,因此可以执行您想要的操作。