Я пытался добавить новую страницу в уже существующий веб-проект, который использует T4MVC в ASP.Net, а также в Razor. Все работает гладко, за исключением одной ошибки: когда я отправляю свою форму, список в модели представления становится пустым, как если бы он не мог создать его с данными.
Я пытался изменить некоторые имена, я пытался удалить и переписать все, я пытался отключить валидатор, думая, что это вызывает проблемы, но безрезультатно. Я также попытался восстановить все, используя файл "T4MVC.tt". Даже в этом случае функциональность в основном копируется с другой страницы, на которой было что-то очень похожее, но все же она работает как шарм (отсюда и классы "tubpicking" в HTML).
Я обнаружил, что это, скорее всего, связано с тем, как "@ Html.HiddenIndexerInputForModel ()" генерирует скрытое индексное поле для поиска MVC, поскольку его значение всегда равно "0", но даже когда я его редактирую вручную, чтобы это выглядело хорошо, я получаю тот же результат.
Любые указатели будут с благодарностью. Я думал, что это ошибка привязки модели, так как я использую ошибку по умолчанию, но насколько я знаю, весь проект опирается на привязку по умолчанию, и она работает.
Вот классы контроллера, viewmodel и view (создание и получение контейнера).
Контроллер:
public partial class ContainerReceptionController : MvcController
{
private readonly IDataTypeService _dataTypeService;
private readonly IHttpContextService _httpContext;
private readonly IEntityRepository<TubPicking> _tubPickingRepository;
private readonly IEntityRepository<Image> _imageRepository;
private readonly IEntityRepository<Company> _companyRepository;
private readonly IContainerServices _containerService;
private readonly IEntityRepository<Client> _clientRepository;
private readonly IEntityRepository<Emplacement> _emplacementRepository;
public ContainerReceptionController(IProviderServices provider, IHttpContextService httpContext)
{
_httpContext = httpContext;
_dataTypeService = provider.GetDataTypeService();
_tubPickingRepository = provider.GetTubPickingRepository();
_imageRepository = provider.GetImageRepository();
_containerService = provider.GetContainerServices();
_companyRepository = provider.GetCompanyRepository();
_clientRepository = provider.GetClientRepository();
_emplacementRepository = provider.GetEmplacementRepository();
}
public virtual ActionResult Create()
{
int ownerId = _httpContext.GetUserOwnerId();
string propertyName = "Owner.Id";
string orderBy = "Id";
string orderType = "ASC";
List<Client> clients = _clientRepository.GetByProperty(propertyName, ownerId.ToString(), orderBy + " " + orderType).ToList();
//Create a view model for the view
ContainerReceptionViewModel createViewModel = new ContainerReceptionViewModel
{
OwnerId = ownerId,
PickingId = 0,
ReceivedContainers = new List<ContainerCreateViewModel>(),
Clients = new SelectList(clients, "ID", "Name")
};
return View(createViewModel);
}
[HttpPost]
public virtual ActionResult Create(ContainerReceptionViewModel viewModel)
{
int ownerId = _httpContext.GetUserOwnerId();
// First, add all the containers in the database
foreach (ContainerCreateViewModel item in viewModel.ReceivedContainers)
{
// Database operations here
}
this.Flash("alert alert-success", UiText.Account.Validation.CREATE_ACCOUNT_SUCCESS);
return RedirectToAction(MVC.Container.Index());
}
// Used in the view to generate new containers
public virtual PartialViewResult AddOperation(string id)
{
int ownerId = _httpContext.GetUserOwnerId();
//Create data lists with a default value
List<DataType> containerTypes = new DataType() { Id = -1, Display = UiText.Container.SELECT_CONTAINER_TYPE }.AsList<DataType>();
List<DataType> materialTypes = new DataType() { Id = -1, Display = UiText.TubPicking.SELECT_MATERIAL_TYPE }.AsList<DataType>();
List<Emplacement> emplacementTypes = new Emplacement() { Id = -1 }.AsList<Emplacement>();
//Add data types to the data lists
containerTypes.AddRange(_dataTypeService.GetAllContainerTypes());
materialTypes.AddRange(_dataTypeService.GetAllMaterialTypes());
emplacementTypes.AddRange(_emplacementRepository.GetByProperty("Owner.Id", ownerId.ToString(), "Id ASC"));
//Create a view model from the data lists
ContainerCreateViewModel containerCreateViewModel = new ContainerCreateViewModel
{
SerialNumber = id,
ContainerTypes = new SelectList(containerTypes, "Id", "Display"),
MaterialTypes = new SelectList(materialTypes, "Id", "Display"),
ContainerEmplacements = new SelectList(emplacementTypes, "Id", "Name")
};
return PartialView("ReceptedContainer", containerCreateViewModel);
}
}
ViewModel:
public class ContainerReceptionViewModel : ViewModel
{
[HiddenInput]
public int PickingId { get; set; }
public int OwnerId { get; set; }
[DisplayName(UiText.Client.CLIENT_NAME)]
public int ClientId { get; set; }
[DisplayName(UiText.ContainerReception.RECEPTION_DATE)]
public DateTime ReceptionDate { get; set; }
public SelectList Clients { get; set; }
public SelectList Emplacements { get; set; }
public bool NeedConfirmation { get; set; }
public List<ContainerCreateViewModel> ReceivedContainers { get; set; }
}
Вид:
@using Externalization
@using Prosyn.Domain
@using Prosyn.Domain.Application
@using Prosyn.Web.ViewModels.TubPickings
@using Prosyn.Web.ViewModels.Containers
@model Prosyn.Web.ViewModels.ContainerReception.ContainerReceptionViewModel
<h2>@UiText.PageTitles.CREATE_CONTAINER_RECEPTION</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="col-md-12">
<div class="col-md-12">
@Html.ValidationMessageFor(model => Model.ReceivedContainers, "", new { @class = "text-danger" })
<hr />
<div class="col-md-3 form-group">
<div>
@Html.LabelFor(model => model.ClientId, htmlAttributes: new { @class = "control-label" })
<div class="input-group">
@Html.DropDownListFor(model => model.ClientId, Model.Clients, UiText.Shipping.SELECT_CLIENT, htmlAttributes: new { @class = "form-control dropdown_search" })
@Html.ValidationMessageFor(model => model.ClientId, "", new { @class = "text-danger" })
</div>
</div>
<div>
@Html.LabelFor(model => model.ReceptionDate, htmlAttributes: new { @class = "control-label" })
<div class='input-group'>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
@Html.EditorFor(model => model.ReceptionDate, new { htmlAttributes = new { @class = "form-control datetime", @id = "arrivalTime" } })
<a href="#" class="btn btn-primary input-group-addon" onclick="timeNow('arrivalTime')"><i class="glyphicon glyphicon-time"></i></a>
</div>
@Html.ValidationMessageFor(model => model.ReceptionDate, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-12">
<div id="TubPickingRows">
@foreach (ContainerCreateViewModel container in Model.ReceivedContainers)
{
Html.RenderPartial("ReceptedContainer", container);
}
</div>
</div>
<div class="btn-group">
<a href="@Url.Action(MVC.ContainerReception.AddOperation(""))" class="btn btn-info btn-outline" id="addTubPicking"><i class="fa fa-plus"></i> @UiText.TubPicking.ADD_OPERATION</a>
</div>
</div>
<div class="form-group">
<div class="col-md-10" style="padding-top: 30px">
<input id="btn-submit" type="submit" value="@UiText.Actions.SAVE" class="btn btn-success" />
@Html.ActionLink(UiText.Actions.RETURN_LIST, MVC.Container.Index(), htmlAttributes: new { @class = "btn btn-default" })
</div>
</div>
</div>
}
<script>
var clickCount = @Model.ReceivedContainers.Count;
$(document).ready(function() {
$(window).keydown(function(event) {
if(event.keyCode === 13) {
event.preventDefault();
return false;
}
return true;
});
});
$("#addTubPicking").click(function () {
clickCount++;
$.ajax({
url: this.href + '?id=@Model.PickingId-' + clickCount,
cache: false,
success: function (html) {
$(html).hide().appendTo($("#TubPickingRows")).fadeIn();
var elements = document.getElementsByClassName("select_all");
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = function() { this.select(); };
}
}
});
return false;
});
function deleteDriverBinPicking(sourceBtn) {
$(sourceBtn).closest('.TubPickingRow').fadeOut('fast', function () { $(sourceBtn).closest('.TubPickingRow').remove(); });
}
function timeNow(id) {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
if (month < 10) month = "0" + month;
var date = (now.getDate() < 10) ? "0" + now.getDate() : now.getDate();
var hour = ((now.getHours() < 10) ? "0" + now.getHours() : now.getHours()) + ":" + ((now.getMinutes() < 10) ? "0" + now.getMinutes() : now.getMinutes());
document.getElementById(id).value = year + "/" + month + "/" + date + " " + hour;
}
function updateForm(formId, color) {
var form = document.getElementById("bin-pickup-" + formId);
if (color === 0) {
form.className = "panel-body panel-background-g";
} else {
form.className = "panel-body panel-background-b";
}
document.getElementById("transfert_form_" + formId).style.display = (color !== 1) ? "none" : "block";
document.getElementById("pickup_form_" + formId).style.display = (color === 1) ? "none" : "block";;
}
</script>
Так же как и частичное представление, которое я использую для визуализации своих контейнеров:
@using Externalization
@using Helpers.Html
@using Prosyn.Web.ViewModels
@model Prosyn.Web.ViewModels.Containers.ContainerCreateViewModel
@using (Html.BeginCollectionItem("ReceptedContainers"))
{
<div class="TubPickingRow">
<div class="col-md-4">
<div class="panel panel-default">
@Html.HiddenIndexerInputForModel()
@Html.HiddenFor(model => model.Id)
<div class="panel-heading">
<a class="btn btn-danger" href="javascript:void(0);" onclick="return deleteDriverBinPicking(this)">
<i class="fa fa-trash-o fa-lg"></i>
</a>
<b class="col-sm-offset-1">@UiText.TubPicking.PICKUP</b>
</div>
<div class="panel-body panel-background-b" id="bin-pickup-@Model.Id">
<div id="data_inputs_@Model.Id">
<div id="transfert_form_@Model.Id" style="display: block">
<div class="col-md-12">
@Html.LabelFor(model => model.SerialNumber, new { @class = "control-label" })
@Html.EditorFor(model => model.SerialNumber, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.SerialNumber, "", new { @class = "text-danger" })
</div>
<div class="col-md-12">
@Html.LabelFor(model => model.ContainerTypeId, new { @class = "control-label" })
@Html.DropDownListFor(model => model.ContainerTypeId, Model.ContainerTypes, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.ContainerTypeId, "", new { @class = "text-danger" })
</div>
<div class="col-md-12">
@Html.LabelFor(model => model.MaterialTypeId, new { @class = "control-label" })
@Html.DropDownListFor(model => model.MaterialTypeId, Model.MaterialTypes, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.MaterialTypeId, "", new { @class = "text-danger" })
</div>
<div class="col-md-12">
@Html.LabelFor(model => model.ContainerEmplacementId, new { @class = "control-label" })
@Html.DropDownListFor(model => model.ContainerEmplacementId, Model.ContainerEmplacements, htmlAttributes: new { @class = "form-control" })
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}