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

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

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

Вопрос:

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

 [MetadataType( typeof( ExceptionLogModel.EmailRecipientMetadata ) )]
public class EmailRecipientViewModel
{
    public int EmailRecipientID { get; set; }

    [Remote( "ValidateEmailRecipientNameUniqueness", "EmailRecipient", ErrorMessage = "Name is not unique." )]
    public string Name { get; set; }

    [Remote( "ValidateEmailRecipientEmailUniqueness", "EmailRecipient", ErrorMessage = "Email is not unique." )]
    public string Email { get; set; }
}

public class EmailRecipientChoices
{
    public List<EmailRecipient> UnselectedEmailRecipients { get; set; }
    public List<EmailRecipient> SelectedEmailRecipients { get; set; }
    public EmailRecipientViewModel EmailRecipient { get; set; }
}
  

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

 http://localhost:55327/EmailRecipient/ValidateEmailRecipientNameUniqueness?Name=sdhsdgh

http://localhost:55327/EmailRecipient/ValidateEmailRecipientNameUniqueness?EmailRecipient.Name=sdhsdgh
  

Вот текущая версия моего метода action, который не работает со вторым URL:

 public JsonResult ValidateEmailRecipientNameUniqueness( string name )
{
    var isValid = !_emailRecipientRepo.NameExists( name );

    return Json( isValid, JsonRequestBehavior.AllowGet );
}
  

При использовании второго URL-адреса параметр name будет равен null. Я читал, что я должен иметь возможность добавить атрибут Bind к этому параметру и добавить префикс, но это тоже не работает. Я даже попытался установить префикс в EmailRecipient. на всякий случай, если ему нужна точка. Я также попробовал использовать его с заглавной буквы N в имени на всякий случай. Не получается. Добавление этого также нарушает его для другого URL!

 public JsonResult ValidateEmailRecipientNameUniqueness( [Bind( Prefix = "EmailRecipient")] string name )
  

Возможные решения

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

Я мог бы использовать перегрузку для @Html.EditorFor() и указать ему использовать «Name» для htmlFieldName, а также использовать @Html.ValidationMessage( "Name" ) вместо ValidationMessageFor . Единственным недостатком этого являются потенциальные конфликты именования, но это не так уж и важно. Мне просто нужно было бы использовать уникальное имя для всех экземпляров этого используемого класса. Обновление: На самом деле, если я это сделаю, это приведет к сбоям при публикации формы, потому что я изменил имена. Это никуда не годится.

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

 string name = Request.QueryString[ "Name" ] ?? Request.QueryString[ "EmailRecipient.Name" ];
  

Это достаточно просто, и я, вероятно, просто собираюсь использовать это. Однако, поскольку у меня уже есть этот вопрос, я спрошу, есть ли более элегантное решение?

Ответ №1:

Ну, я знаю, что это поздно, но есть более элегантное решение:

 public JsonResult ValidateEmailRecipientNameUniqueness (EmailRecipient recipient)
{
    string name = recipient.Name;
    var isValid = !_emailRecipientRepo.NameExists(name);
    return Json(isValid, JsonRequestBehavior.AllowGet);
}
  

Другими словами, используйте саму модель. Он правильно свяжет name свойство, и вам нужно только это значение.

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

1. Это не работает, когда текстовое поле называется просто «name». В этом проблема. У меня было два разных текстовых поля, которые оба хотели использовать один и тот же метод проверки.

2. Я только что протестировал его на своей стороне. Я использовал Fiddler и могу подтвердить: он работает без какого-либо префикса.

3. Причина, по которой это не работает, заключается в том, что у меня две разные модели. У меня есть модель «A», а также модель «B», которая содержит экземпляр модели «A». Удаленный валидатор предназначен для свойства модели «A». Когда я использую модель «B», текстовое поле получает имя «EmailRecipient.Name «потому что это свойство вложенного объекта. Когда я использую только модель «A», текстовое поле называется «Name». Если я использую EmailRecipient в качестве параметра, то он не будет работать, когда текстовое поле названо «EmailRecipient.Name «. Это работает только тогда, когда текстовое поле называется «Name». Вам нужно создать два разных представления, чтобы протестировать это.

4. Для ясности, я только что протестировал это, и это не работает, когда моделью моего представления является EmailRecipientChoices.

Ответ №2:

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