Я пытаюсь следовать рекомендациям онлайн, чтобы создать пользовательское связующее для моделей.Причина, по которой я это делаю, заключается в том, что у меня есть абстрактный класс, из которого я хочу создать экземпляр для детей.У меня есть "MasterTicket
" абстрактный родитель с "MasterTicketItems
" как абстрактный ребенок.
Идея состоит в том, что конкретные дочерние элементы в иерархии наследования будут иметь своих конкретных дочерних элементов (т. Е. Задачи назначения (один дочерний) имеют ApptTaskItems, а общие задачи имеют GenLogItems, инцидентные задачи имеют IncidentLogItems и т. Д.).
Проблема заключается в том, что при создании журнала мой связыватель моделей фактически не связывает данные с конкретными дочерними элементами, которые я хотел вернуть из связывателя моделей.Вот код связывателя модели:
public class MasterTicketItemBinder : DefaultModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Guid ticketId)
{
var values = (ValueProviderCollection)bindingContext.ValueProvider;
IEnumerable<MasterTicket> uptList = StaticDataStore.tickets;
var currTicket = uptList.Single(a => a.id == ticketId);
//var name = (string)values.GetValue("Name").ConvertTo(typeof(string));
return currTicket is ApptTaskTicket ? (MasterTicketItem)new ApptConfirmItem() { ticketItemId = Guid.NewGuid() } : new GenLogItem() { ticketItemId = Guid.NewGuid() };
}
}
Вот мой файл Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
private readonly List<ApptTaskTicket> _initialTickets;
private readonly List<Personnel> _allUsers;
public MvcApplication()
{
_initialTickets = new List<ApptTaskTicket>();
_allUsers = new List<Personnel>();
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ModelBinders.Binders.Add(typeof(MasterTicketItem), new MasterTicketItemBinder());
Application["taskTickets"] = new List<ApptTaskTicket>();
Application["allUsers"] = new List<Personnel>();
}
}
А вот мой MasterTicketItem:
[Table("TicketItem")]
[ModelBinder(typeof(MasterTicketItemBinder))]
public abstract class MasterTicketItem
{
public Guid ticketItemId{ get; set; }
public DateTime createTime{ get; set; }
public bool active{ get; set; }
public DateTime updateTime{ get; set; }
//TODO: Create foreign key relation
public Guid userCreatedId{ get; set; }
public Guid userUpdateId{ get; set; }
public Guid userOwnerId{ get; set; }
public string itemType{ get; set; }
public string itemDescription{ get; set; }
public int timesUpdated{ get; set; }
public DateTime expectedCompletionTime{ get; set; }
public DateTime actualCompletionTime{ get; set; }
public MasterTicketItem()
{
}
}
Кроме того, воткод сообщения JavaScript для рассматриваемого контроллера:
handleLogSubmit(log) {
//e.preventDefault();
const logs = this.state.data.masterTicketItems;
// Optimistically set an id on the new comment. It will be replaced by an
// id generated by the server. In a production application you would likely
// use a more robust system for ID generation.
if (!logs) {
log.ticketItemId = 1;
log.createTime = new Date().toISOString();
log.userCreatedId = this.userState.data.userId;
const newLogs = log;
let masterItemsAccess = Object.assign({}, this.state.data);
masterItemsAccess.masterTicketItems = log;
this.setState(prevData => ({...prevData, data: { ...prevData.data, masterTicketItems: [log], apptConfirmItems: [log] } }));
}
else {
log.ticketItemId = logs.length + 1;
log.createTime = new Date().toISOString();
log.userCreatedId = this.userState.data.userId;
const newLogs = logs.concat([log]);
this.setState(prevData => ({ ...prevData, data: { ...prevData.data, masterTicketItems: newLogs, apptConfirmItems: newLogs } }));
}
const data = new FormData();
data.append('ItemType', log.itemType);
data.append('ItemDescription', log.itemDescription);
data.append('UserCreatedId', log.userCreatedId);
data.append('CreateTime', log.createTime);
data.append("ticketId", this.state.data.id);
const xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.onload = () => this.loadLogsFromServer();
xhr.send(data);
}
Наконец, вот рассматриваемый контроллер, с которым у меня возникают проблемы («не удается создать абстрактный класс»):
[HttpPost]
public ActionResult AddLog([ModelBinder(typeof(MasterTicketItemBinder))]MasterTicketItem log, Guid ticketId)
{
IEnumerable<MasterTicket> uptList = StaticDataStore.tickets;
var currTicket = uptList.Single(a => a.id == ticketId);
MasterTicketItem newLog;
if(currTicket is ApptTaskTicket)
{
newLog = new ApptConfirmItem();
}
else
{
newLog = new GenLogItem();
}
// Create a new ID for this working log
newLog.ticketItemId = Guid.NewGuid();
//ticket.masterTicketItems.Add(log);
if(currTicket.masterTicketItems is null)
uptList.Single(a => a.id == ticketId).masterTicketItems = new List<MasterTicketItem>() { newLog };
else
uptList.Single(a => a.id == ticketId).masterTicketItems.Add(newLog);
Personnel user = (Personnel)Session["loggedInUser"];
uptList.Single(a => a.id == ticketId).userUpdateId = user.userId;
uptList.Single(a => a.id == ticketId).TimesUpdated = Utility.updateIncrement(uptList.Single(a => a.id == ticketId));
StaticDataStore.tickets = uptList;
return Content("Success :)");
}
Можеткто-нибудь, дайте мне знать, что я должен делать здесь?Цель состоит в том, чтобы вернуть класс элемента дочернего билета на основе родительского билета, который передается контроллеру по идентификатору.
Заранее спасибо.