首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ActionMethod中映射模型的最佳位置

在ActionMethod中映射模型的最佳位置
EN

Software Engineering用户
提问于 2020-05-28 14:35:40
回答 2查看 87关注 0票数 -1

我不确定这个问题是否符合这个论坛的目的,但我也不认为它应该属于堆栈溢出问题,所以下面是这样说的:

我创建了一个模型绑定,通过将它放入模型绑定本身,使一个映射变得“干净”,但现在我想用另一种操作方法再次这样做,我只是想知道是否会有更好的方法来实现它,因为我不认为这是正确的地方。

我的动作方法如下所示:

代码语言:javascript
复制
[HttpPost("Register")]
public async Task<IActionResult> Register(
    [FromQuery] UserToRegister userToRegister,
    User user /*This property is never used from the body request, since I set it in my custom Model Binder*/)
{
    var response = await _userService.RegisterAsync(user);
    return Ok(response);
}

我创建了一个定制的Model,其中我将属性从userToRegister映射到user param。这个定制的活页夹看起来是这样的:

代码语言:javascript
复制
public Task BindModelAsync(ModelBindingContext bindingContext)
{
    var values = bindingContext.ValueProvider;
    User user = new User()
    {
        Id = Guid.NewGuid(),
        Name = values.GetValue("Name").FirstValue,
        Password = /*password encrypted*/,
        ...
    };
    bindingContext.Result = ModelBindingResult.Success(user);
    return Task.CompletedTask;
}

你觉得这是个好办法吗?在请求中获取User对象更好,这样我可以稍后修改它吗?我是否应该在ModelBinder中进行此修改(哈希密码、创建新Id等)?

EN

回答 2

Software Engineering用户

发布于 2020-05-29 17:41:02

自定义模型绑定正在取代应用程序中的用例。虽然这在技术上是可行的,但对于大多数人来说,发现这种逻辑深深地隐藏在UI层的架构中是令人惊讶的。此外,您无法利用默认模型绑定器获得的自动数据转换。

您当前的用例似乎只处理字符串,所以这里没有什么大不了的。当用例需要编号或日期时,您将不得不编写手动转换代码,迫使您编写一堆在使用默认模型绑定时不需要编写的锅炉板代码。

我对这类事情一直有点怀疑。它开始变成小鸡巫毒魔法,因为从控制器代码中看不出用例是如何执行的。最小惊讶原则在这里适用。我不希望在这里执行业务用例。这方面的共同之处是:

  • 控制器动作法
  • 控制器方法调用的"service“类。
  • 控制器调用的“工作单位”类
  • 一个控制器调用的“用例”类,如果应用类似于六边形的体系结构

我并不是在判断上述任何一种做法是否是最佳做法。这些只是常见的发现这种行为的地方。

基本上,我希望控制流会像这样:

代码语言:javascript
复制
Browser -> HTTP Request -> MVC framework -> controller -> ??? -> business class

您可以将???替换为可以追溯到控制器启动的方法调用的东西。

票数 0
EN

Software Engineering用户

发布于 2021-06-23 18:18:23

除非逻辑非常复杂,否则控制器没有理由不能执行映射。

代码语言:javascript
复制
[HttpPost("Register")]
public async Task<IActionResult> Register([FromQuery] UserToRegister userToRegister)
{
    var user = new User {
        Name = userToRegister.Name,
        Email = userToRegister.Email
    };
    var response = await _userService.RegisterAsync(user);
    return Ok(response);
}

该代码类型安全,易于理解,并将映射逻辑的代码保存在映射发生的地方附近。所以这是一个很好的默认选择。

如果逻辑非常复杂,可以编写实用程序类或实用程序方法来执行映射;例如,可以为UserToRegister类提供一个ToUser()方法。或者你可以使用像AutoMapper这样的工具。但是,除非您的映射逻辑导致操作方法变得太大,难以理解,否则我不会操心。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/410747

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档