我有一个分层应用程序,它向业务层发送命令(实际上,该应用程序基于ncqrs框架,但我认为它在这里不重要)。
命令看起来像这样:
public class RegisterUserCommand : CommandBase
{
public string UserName { get; set; }
public string Email{ get; set; }
public DateTime RegistrationDate { get; set; }
public string ApiKey {get; set;} // edit
}
这个类没有逻辑,只有数据。
我想让用户输入他们的用户名,电子邮件,我想让系统使用当前日期来构建命令。
创建一个基于RegisterUserCommand的强类型视图,然后在将其发送到业务层之前注入日期和APi Key ?
创建一个RegisterUserViewModel类,用这个类创建视图,并根据视图输入创建命令对象
我写了以下代码(对于解决方案n°2):
public class RegisterController : Controller
{
//
// GET: /Register/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{
var service = NcqrsEnvironment.Get<ICommandService>();
service.Execute(
new RegisterUserCommand
{
RegistrationDate = DateTime.UtcNow,
Email= registrationData.Email,
UserName= registrationData.Name,
ApiKey = "KeyFromConfigSpecificToCaller" // edit
}
);
return View();
}
public class RegisterUserViewModel
{
[Required]
[StringLength(16)]
public string Name { get; set; }
[Required]
[StringLength(64)]
public string Email{ get; set; }
}
}
这个代码正在工作…但我想知道我是否选择了正确的方式…
thanks for advice
[Edit]由于日期时间似乎引起误解,我添加了另一个属性"ApiKey",这也应该设置服务器端,从web层(而不是从命令层)
[Edit 2]尝试Erik的建议并实现我想象的第一个解决方案:
[HttpPost]
public ActionResult Index(RegisterUserCommand registrationCommand)
{
var service = NcqrsEnvironment.Get<ICommandService>();
registrationCommand.RegistrationDate = DateTime.UtcNow;
registrationCommand.ApiKey = "KeyFromConfigSpecificToCaller";
service.Execute(
registrationCommand
);
return View();
}
…
我认为你最好选择#2,在那里你会有一个单独的ViewModel和一个命令。虽然它可能看起来是多余的(在某种程度上),你的命令实际上是从你的web服务器到你的命令处理程序的消息。这些消息的格式可能与ViewModel不同,也不应该如此。如果你按原样使用NCQRS,那么你就必须将你的命令映射到你的AR方法和构造函数。
虽然它可能会节省你一点时间,我认为你把自己归类为在你的ViewModels之后建模你的领域,这不应该是这样的。你的ViewModels应该反映你的用户体验和看到的东西;您的领域应该是您的业务规则和知识的反映,而不是总是反映在您的视图中。
现在看起来似乎要做更多的工作,但请帮自己一个忙,将命令与视图模型分开。你以后会感谢自己的。
我希望这对你有帮助。好运!
我建议将其放入RegisterUserCommand类的构造函数中。这样,默认行为总是将其设置为DateTime。UtcNow,如果你需要显式地设置它你可以把它添加到对象初始化器。当你在项目的其他部分使用这个类,而你忘记显式地设置RegistrationDate时,这也会有帮助。
public class RegisterUserCommand : CommandBase
{
public string UserName { get; set; }
public string Email{ get; set; }
public DateTime RegistrationDate { get; set; }
public RegisterUserCommand()
{
RegistrationDate = DateTime.UtcNow;
}
}
和Controller
public class RegisterController : Controller
{
//
// GET: /Register/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{
var service = NcqrsEnvironment.Get<ICommandService>();
service.Execute(
new RegisterUserCommand
{
Email= registrationData.Email,
OpenIdIdentifier = registrationData.OpenIdIdentifier
}
);
return View();
}
public class RegisterUserViewModel
{
[Required]
[StringLength(16)]
public string Name { get; set; }
[Required]
[StringLength(64)]
public string Email{ get; set; }
}
}
我将使用第1条,并使用system.componentmodel.dataannotations.metadatatype进行验证。
我为另一个SO问题创建了一个示例(答案)。
这允许您将模型保存在另一个库中,验证字段并显示字段,就像您使用DataAnnotations处理内部/私有类一样。我不太喜欢为一个视图创建一个完全独立的类,因为它没有额外的价值,同时必须将数据ORM返回到另一个类。(如果你有额外的值,如下拉列表值,或默认值,那么我认为这是有意义的)。
不是[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{
var service = NcqrsEnvironment.Get<ICommandService>();
service.Execute(
new RegisterUserCommand
{
RegistrationDate = DateTime.UtcNow,
Email= registrationData.Email,
UserName= registrationData.Name,
ApiKey = "KeyFromConfigSpecificToCaller" // edit
}
);
return View();
}
你可以有
[HttpPost]
public ActionResult Index(RegisterUserCommand registrationData)
{
var service = NcqrsEnvironment.Get<ICommandService>();
registrationData.ApiKey = "KeyFromConfigSpecificToCaller";
service.Execute(registrationData);
return View();
}