ASP.NET MVC привязка модели с тире в именах элементов элемента

Я прочесываю интернет, пытаясь найти способ разместить тире из элементов формы в стандартное поведение привязки модели ASP.NET-контроллеров в MVC 2, 3 или даже 4.

Являясь разработчиком интерфейсов, я предпочитаю тире в моем CSS над camelCase или подчеркивания. В моей разметке то, что я хочу сделать, это примерно так:

<input type="text" name="first-name" class="required" />
<input type="text" name="last-name" class="required" />

В контроллере я бы передал объект С#, который будет выглядеть следующим образом:

public class Person
{
      public string FirstName { get; set; }
      public string LastName { get; set; }
      //etc...
}

Есть ли способ расширить класс Controller, чтобы разместить это через некоторое регулярное выражение или другое поведение? Я ненавижу тот факт, что мне нужно сделать что-то вроде этого:

<input type="text" name="person.firstname" class="required" />

или даже это:

<input type="text" name="isPersonAttending" class="required" />

Мысли?

Ответ 1

Вы всегда можете создать собственное связующее устройство.

Вот пример, который реализует связующее, которое поддерживает добавление псевдонимов к свойствам модели:

http://ole.michelsen.dk/blog/bind-a-model-property-to-a-different-named-query-string-field/

И с ним сделайте что-нибудь вроде:

[ModelBinder(typeof(AliasModelBinder))]
public class Person
{
      [BindAlias("first-name")]
      public string FirstName { get; set; }
      [BindAlias("last-name")]
      public string LastName { get; set; }
      //etc...
}

EDIT: Эта реализация, как говорит блогер, основана на ответе Андраса на следующий вопрос SO: Asp.Net MVC 2 - привязать свойство модели к другому имени

Ответ 2

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

Пользовательский поставщик форм

public class DashFormValueProvider : NameValueCollectionValueProvider
{
    public DashFormValueProvider(ControllerContext controllerContext)
    : base(controllerContext.HttpContext.Request.Form, 
    controllerContext.HttpContext.Request.Unvalidated().Form, 
    CultureInfo.CurrentCulture)
    {
    }

    public override bool ContainsPrefix(string prefix)
    {
        return base.ContainsPrefix(GetModifiedPrefix(prefix));
    }

    public override ValueProviderResult GetValue(string key)
    {
        return base.GetValue(GetModifiedPrefix(key));
    }

    public override ValueProviderResult GetValue(string key, bool skipValidation)
    {
        return base.GetValue(GetModifiedPrefix(key), skipValidation);
    }

    // this will convert the key "FirstName" to "first-name".
    private string GetModifiedPrefix(string prefix)
    {
        return Regex.Replace(prefix, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1-").ToLower();
    }
}

Поставщик стоимости Factory

public class DashFormValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }

        return new DashFormValueProvider(controllerContext);
    }
}

Global.asax.cs

ValueProviderFactories.Factories.Add(new DashFormValueProviderFactory());