c# - UnitsNet - 如何在 MVC 中使用它?
问题描述
如何在 MVC Web 应用程序中使用 UnitsNet nuget 包?
例如我有我的对象:
public class UnitsNetTestViewModel
{
public int AnInput { get; set; }
public UnitsNet.Temperature OutdoorTemperature { get; set; }
}
然后我的看法
@model WebApplication.Models.UnitsNetTestViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.LabelFor(model => model.AnInput)
@Html.EditorFor(model => model.AnInput)
<br/>
@Html.LabelFor(model => model.OutdoorTemperature)
@Html.EditorFor(model => model.OutdoorTemperature)
<button type="submit">Submit</button>
}
在我的控制器中
public class UnitsNetTestController : Controller
{
// GET: UnitNetsTest
public ActionResult Index()
{
var model = new Models.UnitsNetTestViewModel {OutdoorTemperature = Temperature.FromDegreesFahrenheit(80)};
return View("~/Views/UnitsNetTest.cshtml", model);
}
[HttpPost]
public ActionResult Index(Models.UnitsNetTestViewModel model)
{
if (ModelState.IsValid)
{
return View("~/Views/Home/Index.cshtml");
}
return View("~/Views/UnitsNetTest.cshtml", model);
}
}
我试过使用EditorFor
or TextBoxFor
。我还尝试在对象的不同部分进行绑定:
model => model.OutdoorTemperature.Value
model => model.OutdoorTemperature.DegreesFahrenheit
model => model.OutdoorTemperature
即使在使用EditorFor
model.OutdoorTemperature
组合时,我也会得到完整的对象输入字段,当我更新一个值时,它总是在控制器提交中返回为零。
我究竟做错了什么 ?
谢谢。
编辑 1
为了了解 UnitsNet 属性是如何工作的,我在模型中添加了一个子类,以查看我的子类值是否可以在控制器中使用(即使我已经知道它会起作用)。我从中注意到:在手表中,我的model.Other
财产的价值是{...WebApplication.Models.SubClass}
,类型也是...WebApplication.Models.SubClass
。但是对于model.OutdoorTemperature
,值是{0 K}
,类型是UnitsNet.Temperature
。这可能是一个线索吗?
更新类:
public class UnitsNetTestViewModel
{
public int AnInput { get; set; }
public UnitsNet.Temperature OutdoorTemperature { get; set; }
public SubClass Other { get; set; }
}
public class SubClass
{
public int Value { get; set; }
public int MySubClassValue { get; set; }
}
更新视图:
@model WebApplication.Models.UnitsNetTestViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.LabelFor(model => model.AnInput)
@Html.EditorFor(model => model.AnInput)
<br />
@Html.LabelFor(model => model.OutdoorTemperature)
@Html.TextBoxFor(model => model.OutdoorTemperature.Value)
<br />
@Html.LabelFor(model => model.Other)
@Html.TextBoxFor(model => model.Other.Value)
<br />
@Html.LabelFor(model => model.Other)
@Html.TextBoxFor(model => model.Other.MySubClassValue)
<button type="submit">Submit</button>
}
编辑 2
这UnitsNet.Temperature
是一个结构,而不是一个类。可能需要一个自定义模型绑定器。
解决方案
最后,MVC 的默认绑定不起作用,因为 UnitsNet 是结构。
我做了一个自定义属性活页夹。
我用这篇文章作为参考: http: //www.stevencwilliams.com/2015/10/26/custom-property-binding-in-asp-net-mvc/
这是使我的示例工作的代码:
public class TemperatureModelBinder : IPropertyBinder
{
public object BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
var propertyValue = controllerContext.HttpContext.Request.Form[propertyDescriptor.Name];
double.TryParse(propertyValue, out var result);
return UnitsNet.Temperature.FromDegreesFahrenheit(result);
}
}
public interface IPropertyBinder
{
object BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor);
}
[AttributeUsage(AttributeTargets.Property)]
public class PropertyBinderAttribute : Attribute
{
public Type BinderType { get; private set; }
public PropertyBinderAttribute(Type binderType)
{
BinderType = binderType;
}
public IPropertyBinder GetBinder()
{
return (IPropertyBinder)DependencyResolver.Current.GetService(BinderType);
}
}
public class ModelBinderBase : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
PropertyBinderAttribute attribute = propertyDescriptor.Attributes
.OfType<PropertyBinderAttribute>()
.SingleOrDefault();
if (attribute == null)
{
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
else
{
propertyDescriptor.SetValue(bindingContext.Model, attribute.GetBinder().BindProperty(controllerContext, bindingContext, propertyDescriptor));
}
}
}
在我的模型中,我添加了我的 binder 属性
[PropertyBinder(typeof(TemperatureModelBinder))]
public UnitsNet.Temperature OutdoorTemperature { get; set; }
在 Global.asax.cs 中,Application_Start()
ModelBinders.Binders.DefaultBinder = new ModelBinderBase();
推荐阅读
- rest - 如何使用 REST API 递归获取 SharePoint 文档库子文件夹、文件夹计数和文件计数?
- c - 是否可以使用具有误导性语法的 for 循环?
- jquery - 使用 Jquery,我可以在移动浏览器中阻止横向模式吗?
- java - 从 html - 本地网站 - java - jsoup 读取实时数据
- openssl - 如何在终端将十六进制哈希转换为二进制?
- python - 使用 Cerberus 基于条件验证依赖关系
- node.js - 如何在我的 nodejs 文件中获取变量的值
- c# - Linq - 如何在 where 子句中使用 2 列
- javascript - Angular *ngIf 与基于结果模型的异步管道内部条件
- android - CS50 Android Pokedex:为什么我的“Catch Pokemon”按钮只能使用一次?