Моя модель описана ниже.Я бы хотел только подмножество полей ссылки для первых 2 элементов в коллекции Application.References.Я хотел бы, чтобы это происходило как на стороне клиента, так и на стороне сервера.У меня есть рабочий метод, который я опишу ниже, но я чувствую, что клиентская сторона довольно хитрая, поэтому я задаюсь вопросом, может ли быть лучший способ справиться с этим.Я хотел бы быть универсальным, если это возможно, потому что у меня есть несколько других коллекций в объекте Application для проверки подмножества.
EF Model
public class Application
{
//...EF framework code...
public EntityCollection<Reference> References
{
//get, set
}
}
public partial class Reference : EntityObject
{
public global::System.String FullName
{
//get, set
}
public global::System.String Relationship
{
//get, set
}
public global::System.String PhoneNumber
{
//get, set
}
public global::int? RelationshipLength //radio button
{
//get, set
}
public global::int? ReferenceType //radio button
{
//get, set
}
}
ReferenceMetaData.cs
[MetadataType(typeof(ReferenceMetadata))]
public partial class Reference
{
}
public class ReferenceMetadata
{
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Full Name")]
public string FullName { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Reference Type")]
public string ReferenceType { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("How long have you known this person?")]
public string RelationshipLength { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Relationship")]
public string Relationship { get; set; }
[DisplayFormat(NullDisplayText = "N/A")]
[DisplayName("Phone")]
public string Phone { get; set; }
//...more properites
}
В настоящее время я использую расширения RuleException и RulesViolationException Стивена Сандерсона из Pro ASP.NET MVC 2 Framework для ручной проверки на стороне сервера следующим образом:
public static class ApplicationBusinessLogic
{
public static void RunServerValidation(Application app)
{
var errors = new RulesException<Application>();
for (int i = 0; i < 3; i ++)
{
if (string.IsNullOrEmpty(app.References.ElementAt(i).FullName))
errors.ErrorFor(x => x.References.ElementAt(i).FullName, "The Full Name for a first and second reference are required.");
if (app.References.ElementAt(i).ReferenceType == null)
errors.ErrorFor(x => x.References.ElementAt(i).ReferenceType, "The Reference Type for a first and second reference are required.");
if (app.References.ElementAt(i).RelationshipLength == null)
errors.ErrorFor(x => x.References.ElementAt(i).RelationshipLength, "The Relationship Length for a first and second reference are required.");
if (string.IsNullOrEmpty(app.References.ElementAt(i).Relationship))
errors.ErrorFor(x => x.References.ElementAt(i).Relationship, "The Relationship for a first and second reference are required.");
if (string.IsNullOrEmpty(app.References.ElementAt(i).Phone))
errors.ErrorFor(x => x.References.ElementAt(i).Relationship, "The Phone Number for a first and second reference are required.");
}
if (errors.Errors.Any())
throw errors;
}
}
Я просто вызываю этот метод RunServerValidation из контроллера, отлавливаю исключения и затем копирую их в ModelState.Это работает нормально, но я не уверен, как справиться с этим на стороне клиента.Если бы я использовал метаданные [Обязательный], все 3 элемента в коллекции будут иметь эти обязательные поля.Я просто хочу 2 из 3.
Клуджый способ, которым я подключил проверку клиента, заключается в указании атрибутов data-val и data-val-required в представлении при рендеринге входных данных, например, так:
@for (int i = 0; i < 3; i++)
{
ViewData.TemplateInfo.HtmlFieldPrefix = "Application.References[" + i + "]";
<h3>Reference @i</h3>
@Html.ValidationMessageFor(model => model.Application.References.ElementAt(i).FullName)
<div class="editor-label">
@Html.LabelFor(model => model.Application.References.ElementAt(i).FullName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Application.References.ElementAt(i).FullName, new { maxlength = "100", data_val="true", data_val_required="The Full Name for a first and second reference are required." })
</div>
@* and so on for other properties... *@
}
Это работает, но это не может быть идеальным.Я думал, может быть, я мог бы сделать общий атрибут ValidationAttribute, но я бы подумал, что это будет сложно.Я думал [RequiredFieldsForFirstXCollectionItems(FirstXItems=2, Fields= new [] {"FullName", "ReferenceType" /* etc */})]
о члене Application.References, но я не уверен, как это сделать в общем виде.Я на правильном пути с этой мыслью, хотя?Тогда я мог бы реализовать клиентскую и серверную стороны таким образом, но это был бы довольно сложный код, я думаю.
Обновление 26.04.2011:
Я думаю, что этовероятно, мне лучше добавить проверку на стороне клиента с помощью плагина jquery.Validation в функции $ (document) .ready, а не помещать атрибуты data-val и data-val-required html5 во входные теги.Тогда, по крайней мере, у меня есть централизованное место для проверки моего клиента.Вот что я сделал:
@*End of Razor View file*@
<script type="text/javascript>
function addValidationRules() {
//references
for (var i = 0; i < 2; i++) {
$("#Application_References_" + i + "__FullName").rules("add", {
required: true,
messages: {
required: "The Full Name for a first and second reference are required."
}
});
//etc. for other properties
}//end for-loop
}//end addValidationRules()
$(document).ready(function () {
addValidationRules();
//more js code...
});
</script>
Конечно, когда я использую файлы ресурсов для сообщений об ошибках, это может немного усложниться, если я решу переместить javascript в файл .js.Я думаю, что если я сохраню функцию в представлении, я смогу читать файл ресурсов по мере необходимости.