Ненавязчивая проверка клиента ASP.Net MVC 3 не работает с выпадающими списками - PullRequest
7 голосов
/ 26 января 2011

У меня есть простой выпадающий список, первый элемент в списке имеет пустое значение. Если я ничего не выбираю в списке, проверка клиента игнорирует это. Я настроил это поле в соответствии с требованиями модели, используя атрибуты аннотации.

 @Html.DropDownListFor(model => Model.CCPayment.State, UnitedStatesStates.StateSelectList)



[Required(ErrorMessage = "State is Required.")]
    public string State
    {
        get
        {
            return _state;
        }
        set
        {
            _state = value;
        }
    }

есть идеи? я что-то упустил?

Ответы [ 5 ]

8 голосов
/ 12 ноября 2011

Это похоже на допустимую ошибку, вот лучший обходной путь, который я нашел в моем поиске:

http://forums.asp.net/t/1649193.aspx

Короче.Вы оборачиваете источник проблемы, DropDownListFor, в пользовательское расширение HTML и вручную извлекаете ненавязчивые правила проверки на стороне клиента, например:

IDictionary<string, object> validationAttributes = htmlHelper.
    GetUnobtrusiveValidationAttributes(
        ExpressionHelper.GetExpressionText(expression),
        metadata
    );

Затем вы комбинируете свой словарь validationAttributes с любым другим HTMLатрибуты передаются в ваш пользовательский помощник, и вы передаете его DropDownListFor

Полный код, который я использую (у меня там тоже есть метка, вы можете не стесняться):

public static IHtmlString DropDownListWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string label, IEnumerable<SelectListItem> items, string blankOption, object htmlAttributes = null)
{
    var l = new TagBuilder("label");
    var br = new TagBuilder("br");

    var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    var mergedAttributes = helper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes))
        {
            object value = descriptor.GetValue(htmlAttributes);
            mergedAttributes.Add(descriptor.Name, value);
        }
    }

    l.InnerHtml = label + br.ToString(TagRenderMode.SelfClosing) + helper.DropDownListFor(expression, items, blankOption, mergedAttributes);
    return MvcHtmlString.Create(l.ToString(TagRenderMode.Normal));
}
4 голосов
/ 26 января 2011

Вы предоставили слишком мало информации, чтобы мы могли точно определить проблему.Возможно, вы забыли включить в свой вид надлежащие ненавязчивые сценарии проверки, но кто знает?Вы не показали свою точку зрения.

Вот полный рабочий пример:

Модель:

public class MyViewModel
{
    [Required(ErrorMessage = "State is Required.")]
    public string State { get; set; }

    public IEnumerable<SelectListItem> States 
    { 
        get
        {
            return Enumerable.Range(1, 5).Select(x => new SelectListItem
            {
                Value = x.ToString(),
                Text = "state " + x
            });
        }
    }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

Вид:

@model AppName.Models.MyViewModel
@{
    ViewBag.Title = "Home Page";
}
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.State)
    @Html.DropDownListFor(
        x => x.State, 
        new SelectList(Model.States, "Value", "Text"), 
        "-- Please select a state --"
    )
    @Html.ValidationMessageFor(x => x.State)
    <input type="submit" value="OK" />
}

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

2 голосов
/ 21 сентября 2011

Я добавил @ class = "required" к атрибутам, как сказал какой-то парень в потоке в codeplex http://aspnet.codeplex.com/workitem/7629, и у меня все заработало =)

1 голос
/ 17 февраля 2012

Это самый простой способ сделать это, просто добавив data-val-*-* атрибуты в HtmlAttributes из DropDownListFor внутри представления. Следующий метод также работает с RemoteValidation, если вам не нужна удаленная проверка, просто удалите элементы, содержащие data-val-remote-*:

        @Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty, 
        new Dictionary<string, object>() { { "data-val", "true" }, 
        { "data-val-remote-url", "/Validation/yourremoteval" }, 
        { "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })

Надеюсь, это может помочь. С наилучшими пожеланиями!

0 голосов
/ 12 апреля 2018

Если проблема заключается в том, что при выборе «пустого» параметра вы не видите подтверждающего сообщения о том, что поле является обязательным, возможно, это связано с тем, как Html Helper генерирует тег параметра для «пустого» параметра. Проблема в пустом значении атрибута.

<select ...>
  <option value="">
  ...
</select>

Я использовал этот однострочный обходной путь для удаления атрибута значения, и он работал как шарм!

$('option[value=""]').removeAttr("value");

Все, что это делает, это удаляет атрибут value из любого элемента 'option' с пустым атрибутом value.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...