UnitsNet - Как использовать его в MVC? - PullRequest
0 голосов
/ 21 ноября 2018

Как использовать пакет Nuget UnitsNet в веб-приложении MVC?

Например, у меня есть мой объект:

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 я получаю полные поля ввода объекта, когда я обновляю значение, оно всегдавернуть в ноль в контроллере submit.

Что я делаю не так?

Спасибо.

РЕДАКТИРОВАТЬ 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 голосов
/ 21 ноября 2018

Наконец, привязка по умолчанию 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));
        }
    }
}

В моей модели я добавил свой атрибут связывателя

    [PropertyBinder(typeof(TemperatureModelBinder))]
    public UnitsNet.Temperature OutdoorTemperature { get; set; }

И в Global.asax.cs, Application_Start()

ModelBinders.Binders.DefaultBinder = new ModelBinderBase();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...