UnitsNet-如何在MVC中使用它?

时间:2018-11-20 21:21:44

标签: c# model-view-controller

如何在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);
    }
}

我尝试使用EditorForTextBoxFor。 我还尝试了绑定到对象的不同部分:

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。 可能是个线索吗?

这是打印屏幕: Debugging Watch Printscreen

更新的课程:

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是一个结构,而不是一个类。可能需要自定义模型活页夹。

1 个答案:

答案 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();