Пользовательский связыватель модели для десятичных и целых чисел: как получить строковое значение перед MVC и сделать более умное преобразование - PullRequest
3 голосов
/ 16 марта 2011

Я хочу расширить привязку модели по умолчанию, чтобы быть более умным при работе с числами.По умолчанию работает очень плохо, когда в игре используются запятые и десятичные точки.

Я пытался сделать новое связующее

Public Class SmartModelBinder
    Inherits DefaultModelBinder
    Protected Overrides Sub SetProperty(controllerContext As ControllerContext, bindingContext As ModelBindingContext, propertyDescriptor As System.ComponentModel.PropertyDescriptor, value As Object)
        If propertyDescriptor.PropertyType Is GetType(Decimal) Or propertyDescriptor.PropertyType Is GetType(Decimal?) Then
            If value Is Nothing Then
                value = 0
            End If
        End If

        MyBase.SetProperty(controllerContext, bindingContext, propertyDescriptor, value)
    End Sub
End Class

Но значение уже преобразовано в этот момент

Как расширить связыватель, чтобы получить строковое значение из формы и выполнить другое преобразование?

Ответы [ 3 ]

6 голосов
/ 16 марта 2011

Как насчет этого?

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder())

И пользовательский переплет.Наверное, я не знаю, можно ли таким образом переопределить десятичную привязку, но это работает для моих собственных типов.

public class DecimalModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == null)
        {
            return base.BindModel(controllerContext, bindingContext);
        }
        // to-do: your parsing (get the text value from valueProviderResult.AttemptedValue)
        return parsedDecimal;
    }
}
2 голосов
/ 16 марта 2011

Метод, который вы, вероятно, ищете, это BindModel. Вот краткий обзор того, как работает механизм связывания моделей по умолчанию, предположим, у вас есть следующий класс:

public class MyModel
{
  public int Id;
  public string Name;
}

Когда MVC пытается привязать данные к MyModel, он вызывает BindModel в связывателе модели по умолчанию. Этот связыватель определяет, что MyModel не является «простым» типом данных (то есть int, decimal, string и т. Д.). Затем он извлекает возможные члены, с которыми он может связываться, затем находит правильный связыватель модели для каждого из этих типов и вызывает метод связывания модели BindModel для поля / свойства, поэтому связывание модели сложного типа действительно рекурсивно. звоните.

Обычно я бы предложил написать связыватель модели только для десятичного числа и установить его в качестве связывателя модели для этого типа данных, но я слышал, что у других были проблемы с этим (я сам не пробовал). Поэтому сначала я попробую это, и если это не сработает, то просто проверьте этот тип модели в методе BindModel связывателя модели по умолчанию и обработайте этот особый случай.

Это очень общий обзор привязки модели, и он даже не стал бы предполагать, что это все, что вам нужно знать о том, как работает эта область.

1 голос
/ 20 марта 2011

Я добавляю дополнительный ответ, потому что Фил Хэк недавно написал в блоге, как именно это сделать. Он предупреждает, что это не проверено, но он использует ModelState и добавляет, если необходимо, ошибку, о которой я никогда не знал, когда и как это делать, поэтому это было полезно для меня.

Вот ссылка на его пост: http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx

...