Удаленная проверка кажется глючной

#asp.net-mvc #validation #asp.net-mvc-3 #remote-validation

#asp.net-mvc #проверка #asp.net-mvc-3 #удаленная проверка

Вопрос:

представьте себе такую ситуацию:

Настройка

в проекте MVC3 по умолчанию создайте новый сложный тип в AccountModels.cs

 public class GlobalAccount
{
    public GlobalAccount()
    {
        this.LogOn = new LogOnModel();
        this.Register = new RegisterModel();
    }

    public LogOnModel LogOn { get; set; }
    public RegisterModel Register { get; set; }
}
  

В RegisterModel измените UserName на:

 [Required]
[Remote("UserNameExists", "Validation", "", ErrorMessage = "Username is already taken.")]
[RegularExpression(@"(S) ", ErrorMessage = "White space is not allowed.")]
[Display(Name = "Username (spaces will be stripped, must be at least 6 characters long)")]
public string UserName { get; set; }
  

UserNameExists Метод в Validation контроллере заключается в следующем:

 public class ValidationController : Controller
{
    public JsonResult UserNameExists(string UserName)
    {
        string user = null;
        if (!String.IsNullOrWhiteSpace(UserName) amp;amp; UserName.Length >= 6)
            user = UserName == "abcdef" ? "ok" : null;

        return user == null ?
            Json(true, JsonRequestBehavior.AllowGet) :
            Json(string.Format("{0} is not available.", UserName), JsonRequestBehavior.AllowGet);
    }
}
  

Теперь в представлении регистра используйте GlobalAccount модель вместо RegisterModel

поле ввода имени пользователя будет выглядеть:

 @model Your.NameSpace.Models.GlobalAccount
  

и

  <div class="field fade-label">
    @Html.LabelFor(model => model.Register.UserName, new { @class = "text" })
    @Html.TextBoxFor(model => model.Register.UserName, new { spellcheck = "false", size = "30" })
</div>
  

это приведет к чему-то подобному в HTML

 <div class="field fade-label">
    <label class="text" for="Register_UserName"><span>Username (spaces will be stripped, must be at least 6 characters long)</span></label>
    <input data-val="true" data-val-regex="White space is not allowed." data-val-regex-pattern="(S) " data-val-remote="Username is already taken." data-val-remote-additionalfields="*.UserName" data-val-remote-url="/beta/Validation/UserNameExists" data-val-required="The Username (spaces will be stripped, must be at least 6 characters long) field is required." id="Register_UserName" name="Register.UserName" size="30" spellcheck="false" type="text" value="">
</div>
  

Отладка

Если вы используете FireBug для проверки того, что происходит… удаленная проверка отправляет имя атрибута вместо идентификатора методу проверки ( UserNameExists одному) как:

Register.UserName вместо Register_UserName

Поэтому я не могу получить это значение… когда-либо:(

Это действительно ошибка или что-то, что кто-то уже нашел, и я не смог получить, погуглив это?

Вот простое изображение реальной проблемы:

введите описание изображения здесь

Ответ №1:

Как насчет:

 public ActionResult UserNameExists(
    [Bind(Include = "UserName")]RegisterModel register
)
{
    string user = null;
    if (!String.IsNullOrWhiteSpace(register.UserName) amp;amp; register.UserName.Length >= 6)
        user = register.UserName == "abcdef" ? "ok" : null;

    return user == null ?
        Json(true, JsonRequestBehavior.AllowGet) :
        Json(string.Format("{0} is not available.", register.UserName), JsonRequestBehavior.AllowGet);
}
  

Другой возможностью является определение специальной модели представления:

 public class UserNameExistsViewModel
{
    public string UserName { get; set; }
}
  

и затем:

 public ActionResult UserNameExists(UserNameExistsViewModel register)
{
    string user = null;
    if (!String.IsNullOrWhiteSpace(register.UserName) amp;amp; register.UserName.Length >= 6)
        user = register.UserName == "abcdef" ? "ok" : null;

    return user == null ?
        Json(true, JsonRequestBehavior.AllowGet) :
        Json(string.Format("{0} is not available.", register.UserName), JsonRequestBehavior.AllowGet);
}
  

Что раздражает, так это то, что следующее не работает:

 public ActionResult UserNameExists(
    [Bind(Prefix = "Register")]string UserName
)
  

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

Комментарии:

1. Я был здесь, смотрел на экран и желал, чтобы ты был онлайн, Дарин 🙂 … Я должен сказать: ВАУ… Я никогда раньше не видел этого трюка, и он работает просто очаровательно 🙂 Разве нам не нравится узнавать что-то новое о нашем любимом языке : D — Мне просто грустно, что я не могу добавить 10 : ( — Очень признателен, Дарин!

2. Я обнаружил, что то, что «раздражает» Дарина, работает для меня, где Bind (Include =»bla») не сработал.

Ответ №2:

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

Класс в моем случае — «Food», а поле, которое я пытаюсь удаленно проверить, — «Name». Текстовое поле создается редактором для управления:

 @Html.EditorFor(model => model.Name)
  

Удаленная проверка установлена в поле класса питания:

 [Remote("FoodNameExists")]
public string Name { get; set; }
  

И это вызывает метод:

 public ActionResult FoodNameExists(string Name) {
  

Согласно исходному вопросу, вместо того, чтобы передавать это методу FoodNameExists как «Name» или даже «Food_Name», который является значением идентификатора, созданным помощником EditorFor, оно передается как атрибут name, который является «Food.Name «… что, конечно, не является чем-то, что я могу установить в качестве входного параметра.

Итак, мой взлом заключается в том, чтобы просто игнорировать входные параметры и искать в строке запроса:

 var name = Request.QueryString["Food.Name"];
  

… это возвращает правильное значение, которое я проверяю, и я отправляюсь на гонки.

Ответ №3:

Это самый простой способ, который я нашел, чтобы сделать это, просто добавив атрибуты data-val- в htmlAttributes выпадающего списка for, внутри представления. Следующий метод также работает с удаленной проверкой, если вам не нужна удаленная проверка, просто удалите элементы, содержащие 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" } })
  

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