MVC 4-具有抽象类的自定义模型绑定

时间:2019-04-30 03:23:58

标签: asp.net-mvc-4 model-binding custom-model-binder

我正在尝试遵循在线建议以创建自定义模型活页夹。我这样做的原因是因为我有一个抽象类,希望让孩子实例化。我有一个“ MasterTicket”抽象父级,其中“ MasterTicketItems”是抽象子级。

该想法是继承层次结构中的具体子级将具有其具体子级(即,约会任务(一个子级)具有ApptTaskItems,常规任务具有GenLogItems,事件任务具有IncidentLogItems等)。

问题是,当创建日志时,我的Model Binder似乎并没有将数据实际绑定到我本来希望从Model Binder返回的具体子项上。这是Model Binder的代码:

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()
    {

    }
}

此外,这是有问题的Controller的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 :)");
}

有人可以让我知道我应该在这里做什么吗?目标是根据通过ID传递给控制器​​的父票证返回子票证项目类。

谢谢。

0 个答案:

没有答案