Во-первых, да, вы можете улучшить синтаксис своего представления.Используйте EditorTemplates .
Создать Views\Shared\EditorTemplates\GridRow.cshtml
:
@model TestMvc.Models.TableFormTestModel.GridRow
<div>
@Html.HiddenFor(x => x.Id)
@Html.TextBoxFor(x => x.Name)
@Html.ValidationMessageFor(x => x.Name)
</div>
Теперь ваш основной вид должен быть только:
@model TableFormTestModel
@using (Html.BeginForm())
{
Html.EnableClientValidation();
Html.EnableUnobtrusiveJavaScript();
@Html.EditorFor(x => x.GridData)
}
Что касается проблем с RemoteAttribute, это сложно.Проблема связана с именами входов, которые MVC создает для массивов.Как видите, ваши входные данные имеют названия, например, GridData[1].Id
, GridData[1].Name
(и т. Д.).Что ж, jQuery выполняет свой вызов ajax, передавая эти имена в строку запроса.
Таким образом, в итоге вызывается:
/Admin/TableFormTest/IsNameAvailable?GridData%5B1%5D.Name=sdf&GridData%5B1%5D.Id=5
aka
/Admin/TableFormTest/IsNameAvailable?GridData[1].Name=sdf&GridData[1].Id=5
...и стандартная подшивка модели действительно не знает, что с этим делать.
Я предлагаю написать свою собственную подшивку модели.Скажите MVC, как прочитать эту строку запроса, а затем создать нужный объект.
Вот подтверждение концепции.( Но не используйте эту вещь в производстве : она принимает слишком много допущений и вылетает и сгорает при любых неожиданностях.)
public class JsonGridRowModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
var model = new TableFormTestModel.GridRow();
var queryString = controllerContext.HttpContext.Request.QueryString;
model.Name = queryString[queryString.AllKeys.Single(x => x.EndsWith("Name"))];
string id = queryString[queryString.AllKeys.Single(x => x.EndsWith("Id"))];
model.Id = string.IsNullOrWhiteSpace(id) ? 0 : int.Parse(id);
return model;
}
}
Затем скажите вашему IsNameAvailable
методу использоватьэта модель переплета:
public JsonResult IsNameAvailable([ModelBinder(typeof(JsonGridRowModelBinder))] TableFormTestModel.GridRow gridRow) {
...
}