具有自定义格式的 ASP.NET MVC ViewModel 映射

2024-04-27

我正在从事的项目在域模型中有大量货币属性,我需要将它们格式化为$#,###.##用于向视图传输和从视图传输。我对可以使用的不同方法有一个想法。一种方法可能是在视图内显式设置值的格式,如下所示Steve Michelotti 的“模式 1” https://web.archive.org/web/20210124230412/http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx :

...但这开始违反干原则 https://en.wikipedia.org/wiki/Don%27t_repeat_yourself非常快。

首选方法似乎是在 DomainModel 和 ViewModel 之间的映射期间进行格式化(根据ASP.NET MVC 实际应用 https://www.manning.com/books/asp-net-mvc-in-action第 4.4.1 节和“模式3” https://web.archive.org/web/20210124230412/http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx)。使用 AutoMapper,这将产生如下所示的代码:

[TestFixture]
public class ViewModelTests
{
 [Test]
 public void DomainModelMapsToViewModel()
 {
  var domainModel = new DomainModel {CurrencyProperty = 19.95m};

  var viewModel = new ViewModel(domainModel);

  Assert.That(viewModel.CurrencyProperty, Is.EqualTo("$19.95"));
 }
}

public class DomainModel
{
 public decimal CurrencyProperty { get; set; }
}

public class ViewModel
{
 ///<summary>Currency Property - formatted as $#,###.##</summary>
 public string CurrencyProperty { get; set; }

 ///<summary>Setup mapping between domain and view model</summary>
 static ViewModel()
 {
  // map dm to vm
  Mapper.CreateMap<DomainModel, ViewModel>()
   .ForMember(vm => vm.CurrencyProperty, mc => mc.AddFormatter<CurrencyFormatter>());
 }

 /// <summary> Creates the view model from the domain model.</summary>
 public ViewModel(DomainModel domainModel)
 {
  Mapper.Map(domainModel, this);
 }

 public ViewModel() { }
}

public class CurrencyFormatter : IValueFormatter
{
 ///<summary>Formats source value as currency</summary>
 public string FormatValue(ResolutionContext context)
 {
  return string.Format(CultureInfo.CurrentCulture, "{0:c}", context.SourceValue);
 }
}

Using IValueFormatter这种方法效果很好。现在,如何将其从领域模型映射回视图模型?我尝试过使用自定义class CurrencyResolver : ValueResolver<string,decimal>

public class CurrencyResolver : ValueResolver<string, decimal>
{
 ///<summary>Parses source value as currency</summary>
 protected override decimal ResolveCore(string source)
 {
  return decimal.Parse(source, NumberStyles.Currency, CultureInfo.CurrentCulture);
 }
}

然后将其映射为:

  // from vm to dm
  Mapper.CreateMap<ViewModel, DomainModel>()
   .ForMember(dm => dm.CurrencyProperty, 
    mc => mc
     .ResolveUsing<CurrencyResolver>()
     .FromMember(vm => vm.CurrencyProperty));

这将满足这个测试:

 ///<summary>DomainModel maps to ViewModel</summary>
 [Test]
 public void ViewModelMapsToDomainModel()
 {
  var viewModel = new ViewModel {CurrencyProperty = "$19.95"};

  var domainModel = new DomainModel();

  Mapper.Map(viewModel, domainModel);

  Assert.That(domainModel.CurrencyProperty, Is.EqualTo(19.95m));
 }

...但我觉得我不需要明确定义它是从哪个属性映射的FromMember做完之后ResolveUsing由于属性具有相同的名称 - 是否有更好的方法来定义此映射?正如我所提到的,有大量具有货币价值的属性需要以这种方式进行映射。

话虽这么说,有没有办法通过全局定义一些规则来自动解析这些映射? ViewModel 属性已被装饰DataAnnotation属性[DataType(DataType.Currency)]为了验证,所以我希望我可以定义一些规则:

if (destinationProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency)) 
  then Mapper.Use<CurrencyFormatter>()
if (sourceProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency)) 
  then Mapper.Use<CurrencyResolver>()

...这样我就可以最大限度地减少每种对象类型的样板设置数量。

我也有兴趣了解任何用于完成视图之间的自定义格式设置的替代策略。


From ASP.NET MVC 实际应用 https://www.manning.com/books/asp-net-mvc-in-action:

一开始我们可能会想通过 这个简单的对象直接 视图,但是日期时间?特性 [在模型中]会引起问题。 例如,我们需要选择一个 为它们格式化,例如 ToShortDateString() 或 ToString()。这 视图将被迫做空 检查以防止屏幕 当属性爆炸时 无效的。视图难以统一 测试,所以我们想让它们保持薄 尽可能。因为输出一个 view 是传递给的字符串 响应流,我们只会使用 字符串友好的对象;那 是,永远不会失败的对象 对它们调用 ToString()。这 ConferenceForm 视图模型对象是 这方面的例子。上市通知 4.14 所有属性都是字符串。我们会正确确定日期 在此视图模型之前格式化 对象放置在视图数据中。这 方式,视图不需要考虑 对象,并且它可以格式化 信息正确。


您是否考虑过使用扩展方法来格式化货币?

public static string ToMoney( this decimal source )
{
    return string.Format( "{0:c}", source );
}


<%= Model.CurrencyProperty.ToMoney() %>

由于这显然是一个与视图相关(而不是与模型相关)的问题,因此如果可能的话,我会尝试将其保留在视图中。这基本上将其移动到十进制的扩展方法,但用法是在视图中。您还可以做一个 HtmlHelper 扩展:

public static string FormatMoney( this HtmlHelper helper, decimal amount )
{
    return string.Format( "{0:c}", amount );
}


<%= Html.FormatMoney( Model.CurrencyProperty ) %>

如果你更喜欢那种风格。它在某种程度上与视图相关,因为它是 HtmlHelper 扩展。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有自定义格式的 ASP.NET MVC ViewModel 映射 的相关文章

  • C# 查询两个数据库的数据

    我目前有一个查询 我正在从两个不同的数据库获取数据 这些数据被附加到一个名为 accountbuys 的列表中 我的第一个表有三个数据条目 3个想要购买股票的帐户 下一张表有 17 个数据点 购买 17 只股票 I am merging t
  • 从 viewModel 在 Asp.net MVC 3 上实现 Dropdownlist

    我是 net 和 mvc 平台的新手 我有很多 int 字段来存储一些下拉列表值 由于数据库大小 我创建了 int 类型的字段 所以我通过这种方法实现 dropdownlist 它有效 但我不这样做不知道在视图模型上存储值文本是否是正确的解
  • 将 Json 数据返回给 Ajax 调用

    我在 MVC 中有一个方法 我将其发布到它 并且我需要返回一些数据以进行处理 这是我发布到的 MVC 方法 返回值是 json 数据 HttpPost public JsonResult GetCalculateAmortizationSc
  • App_Web_XXX.dll 中发生 System.NullReference 异常 - 部分视图中出现错误

    当登陆我的 MVC 页面之一时 我收到此错误 dll 名称中包含随机字符串 类型的第一次机会异常系统 NullReferenceException发生在 App Web cjmhrrqn dll 中 附加信息 未将对象引用设置为对象的实例
  • 正则表达式 - 剥离非数字并删除分(如果有)

    我目前正在开发一个 PHP 项目 需要一些正则表达式的帮助 我希望能够获取用户输入的货币值并删除所有非数字和小数位 分 Ex 2 000 00 到 2000 2 000 00 美元 到 2000 2abc000 到 2000 2 000 到
  • MVC 中的 Blazor:组件被渲染,但 @onclick 不起作用。连接问题

    我正在尝试在 net core 3 MVC 项目中使用 Blazor 我使用了一些教程来做到这一点 例如https fizzylogic nl 2019 08 18 integrating blazor in an existing asp
  • 如何使用 EF Code First 解释枚举类型

    这是一个模型 Public class Person Key Public int PersonId get set Public int Age get set Public ColorEnum FavoriteColor get set
  • 我可以在 ASP.NET MVC 中使用 [CompressFilter] 而不破坏甜甜圈缓存吗

    我正在努力获得 压缩过滤器 http www thegrubbsian com p 202 使用甜甜圈缓存并遇到问题 发生的情况是整个页面都被缓存 而不仅仅是甜甜圈 的来源CompressFilter我正在使用的是下面的 我从原始来源 ht
  • asp.net MVC 1.0和2.0货币模型绑定

    我想创建模型绑定功能 以便用户可以输入 等等 用于绑定到我的 ViewModel 的双精度值的货币值 我能够在 MVC 1 0 中通过创建自定义模型绑定器来执行此操作 但是自从升级到 MVC 2 0 后 此功能不再起作用 有谁有任何想法或更
  • 当视图模型类型为包含超过 4 个项目的元组时,Asp.net mvc 2 .net 4.0 出现错误

    当我在 Asp net mvc 2 net 4 0 中使用模型类型 Tuple 创建强类型视图时 当 Tuple 具有超过 4 个项目时 我会收到错误 示例1 视图类型是Tuple
  • 为什么这条路线不匹配

    我在获取匹配路线时遇到一些问题 我使用 base 32 编码的 int 作为 Web 应用程序中幻灯片的短链接 每个幻灯片有 5 个不同的版本 我使用首字母来区分每个版本 路由始终匹配 除非 Base 32 编码 int 的第一个字符与指定
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • MVC ASP.NET 或 Razor

    我对 MVC 很陌生 我对 Silver light WPF 和 MVVM 有相当多的了解 但对 MVC 知之甚少 我正在按照 Microsoft 网站上的主要教程进行操作http www asp net mvc tutorials get
  • 纠正我在 mvc 中的 url 路由

    在我的 global asax 文件中 我有一个注册路由 routes MapRoute Default Route name controller action id URL with parameters new controller
  • 每个其他请求 JWT 验证都会失败,并显示“idx10503 签名验证失败”。令牌没有孩子'

    所以整个 JWT 签名和验证对我来说还是很新鲜的 我现在有一个 C 应用程序 它通过使用 JWT 保护的 API 请求一些信息 奇怪的是 所有其他请求都失败了 所以第一个请求就像一个魅力 我收到了我期望的信息和回复 JWT 验证成功 我在它
  • 如何在单击按钮时重新绑定 igGrid igniteUI 控件中的数据?

    我在 ASP NET MVC3 应用程序中使用 Infragistics Ignite UI 控件 我有一个已绑定到 客户 数据的网格 工作正常 现在我有按钮了 单击后我会进行 ajax 调用 在控制器中 我编写了仅选择 客户 数据的一部分
  • jsFiddle 中的 jQuery 不显眼的自定义适配器和方法

    我无法使 jsFiddle 工作 但它可以在浏览器中工作 http jsfiddle net vtortola jYq2X http jsfiddle net vtortola jYq2X 我正在尝试添加新的自定义规则来比较两个字段 自定义
  • 实体框架:在运行时更改连接字符串

    假设有一个 ASP NET MVC 应用程序使用 Entity Framework 6 和代码优先方法以及 StructureMap 作为 IoC 它还使用工作单元模式 域类 public class Product public int
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • 您如何填充/验证您的 ViewModel?

    我很好奇人们构建 ViewModel 的各种方式以及他们为什么选择该方法 我在这里可以想到几种方法 1 注入存储库 控制器加载模型并映射到 ViewModel 这里 ViewModel 构造函数可以采用各种集合来进行内部设置 在选择列表中

随机推荐

  • python3导入找不到模块

    我正在尝试测试书中的一个例子 我得到了一个ImportError 该示例开始如下 from tkinter import from PP4E Gui Tools widgets import frame button entry 如果我放一
  • 如何使用 Android Studio 调试器后退一行代码

    我是调试器的新手 当我跨过一行代码时 我想知道如何后退 现在我意识到代码不能向后执行 如果我想退回到旧行 是否必须重新启动调试活动 另外 如果您不介意的话 强制步入命令是什么 不要认为这是可能的 Android 的工作方式与所有其他调试器一
  • java 对字母数字字符串进行排序

    我有这个数组存储用户添加的一些 URL 的后缀 U2 U3 U1 U5 U8 U4 U7 U6 当我这样做时 for Map
  • 调用程序中对库类成员的未定义引用错误

    下面添加了其他问题 2011 年 4 月 11 日 我正在用 C 开发一组跨平台的共享库 DLL Sos 和测试程序 尽管我必须能够支持 C 这些库将仅作为目标代码发布 但测试程序将随源代码一起发布 因此我们的客户可以获得示例代码 因此 我
  • 使用 Go 解组嵌套 xml

    我有以下代码片段 我一直在努力让它工作 我到处寻找解决方案 但我找到的解决方案似乎都不起作用 我的映射似乎有问题xml Unmarshal命令 因为它涉及嵌套字段 下面的代码用于检索第一个被称为的值unit 并且位于 xml 代码的顶层 另
  • WPF 进度条动画速度

    我注意到 WPF 进度栏和 WinForms 进度栏完全填满所需的时间存在差异 完全填充 就像在 Form 和 WPF 中将值设置为 100 一样 我们可以注意到 WinForms 平滑地填充栏 而 WPF 立即填充它 我想知道是否有一个属
  • 如何摆脱“Google 地图方向服务”标记?

    谷歌地图Direction ServiceApi有两个 副作用 1 它添加了Markers自动到达出发地和目的地 2 它增加了两个InfoWindow到新的Markers 包含他们的地址 知道如何摆脱这些标记及其信息气泡吗 添加suppre
  • QSpinBox 具有用于十六进制输入的 Unsigned Int

    这里写了很多关于 QSpinBox 使用 int 作为其数据类型的限制的问题 人们通常希望显示更大的数字 就我而言 我希望能够以十六进制显示无符号 32 位整数 这意味着我希望我的范围为 0x0 0xFFFFFFFF 正常的 QSpinBo
  • 如何使用 Dapper 将字符串作为 NULL 发送到 SQLServer?

    我有一个场景 C 中的字符串可以是null 我需要它是NULL在 SQL Server 上 我使用 Dapper 将其发送到 SQLServer 查询如下 connection Query
  • 面向 Clojure 用户的 Java

    我一直在断断续续地使用 Lisp 并且正在赶上 clojure clojure的好处是我可以自然地使用所有的java函数 而clojure的坏处也是我必须自然地了解java函数 例如 我不得不花一些时间 谷歌搜索 来查找 Java 中的平方
  • 如何在 AngularJS 中插入命令或阻止 $http 的 JSONP 自动解析?

    似乎我发现的关于 http 或 angularjs 的几乎每个问题或解释通常都假设您可以修改请求的响应 我不能这样做 而且我得到的响应格式错误 根据 AngularJS 解析器 它的格式错误一致 因此我可以在解析纯文本之前修改它来解决问题
  • 当我传递 NULL 值时,COALESCE 函数不起作用,但当将变量声明为 NULL 时它起作用

    当我执行以下查询时 我得到输出 但是当我通过NULL参数 它不起作用 示例1 DECLARE a int NULL b int NULL c int NULL SELECT COALESCE a b c GO 输出 空 示例2 SELECT
  • 如何使用 jasper 从 jsp 生成 pdf 格式的报告

    在我的应用程序中 我可以连接到数据库并获取数组结果集 并使用 JSP 代码迭代该数组并使用 HTML 在网页中显示报告 我希望 HTML 网页中生成的报告可以以 PDF 格式导出并保存在某个 pdf 文件中 请告诉我如何实现这样的技术来实现
  • 雪豹中的 OpenVRML(来自 macports)

    嘿 我刚刚从 macports 下载了 openvrml 端口安装openvrml 现在我有一个示例程序 来自 sourceforge 的 openvrml 的 pretty print cpp 其开头如下 ifdef HAVE CONFI
  • 如何序列化其类相互引用的类层次结构,但避免 XmlInclude?

    我有一个类的层次结构 我想使用XmlSerializer类及其相关属性 有一个基本抽象类 然后是相当多的派生类 在下面的代码中 我已将派生类的数量减少到五个 但实际代码中还有更多 这些类形成一个层次结构 并且经常包含对层次结构中类的实例的引
  • 如何从 iPhone/iPad 删除应用程序及其设置

    我正在 iPhone iPad 上测试应用程序安装 但我只能执行一次 因为 iOS 会记住设置 例如允许访问照片等 并且在我卸载应用程序时永远不会清除它们 因此 下次我安装它时 它不会要求允许访问照片等 除了重置设备之外 还有什么方法可以完
  • 给定一个范围列表,我们如何找到给定值是否存在于 Node js 的该范围列表中

    我有一组 ip 范围 我需要查找用户给出的 ip 是否存在于给定的 ip 范围列表之间 这是这个问题的延续 如何使用node js检查给定的ip是否在给定的ip范围内 https stackoverflow com questions 46
  • 在 Silverlight 中编辑并继续?

    Edit And Continue 是我最喜欢的调试工具之一 我之前曾在基于 C 的 Winforms 和 ASP NET 项目中使用过它 但是 我在 VS 2008 上运行 Silverlight 3 0 应用程序 每当我尝试进行更改 中
  • 为什么需要修改 JSP 中的 buffer 和 autoflush 属性?

    我不明白为什么需要修改JSP中的buffer和autoflush属性 它们是做什么的 如果我不修改它们会发生什么 JSP 页面生成的任何内容都存储在缓冲区中 当缓冲区已满时 它会被发送回客户端 浏览器 当缓冲区刷新一次时 重定向或转发将不起
  • 具有自定义格式的 ASP.NET MVC ViewModel 映射

    我正在从事的项目在域模型中有大量货币属性 我需要将它们格式化为 用于向视图传输和从视图传输 我对可以使用的不同方法有一个想法 一种方法可能是在视图内显式设置值的格式 如下所示Steve Michelotti 的 模式 1 https web