如何在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
或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
是一个结构,而不是一个类。可能需要自定义模型活页夹。
答案 0 :(得分:0)
最后,由于UnitsNet是结构,因此MVC的默认绑定无效。
我做了一个自定义属性绑定器。
我将这篇文章用作参考: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));
}
}
}
在模型中,我添加了活页夹属性
[PropertyBinder(typeof(TemperatureModelBinder))]
public UnitsNet.Temperature OutdoorTemperature { get; set; }
在Global.asax.cs中,Application_Start()
ModelBinders.Binders.DefaultBinder = new ModelBinderBase();