我有一个包含5个步骤的向导,每个步骤都有一个实现IUserAddUpdateStep Interface的视图模型。

我的控制器中的操作方法如下所示

[HttpPost]
public ActionResult AddUpdate(IUserAddUpdateStep step)


还有一个DefaultModelBinder重写,使ASP.NET知道如何处理IUserAddUpdateStep并为上述控制器操作方法AddUpdate的HTTP帖子获取反序列化的具体类型:

 public class StepViewModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            ValueProviderResult stepTypeValue = bindingContext.ValueProvider.GetValue("StepType");
            Type stepType = Type.GetType((string)stepTypeValue.ConvertTo(typeof(string)), true);
            object step = Activator.CreateInstance(stepType);
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => step, stepType);
            return step;
        }
    }


我在AddUpdate.cshtml视图中发布类型为“ IUserAddStep”的视图模型,如下所示:

@model UserAddUpdate

@{
    IUserAddUpdateStepcurrentStep = Model.Steps[Model.CurrentStepIndex];
}

@using (Html.BeginForm("AddUpdate", "Employee", FormMethod.Post, new { @role = "form" }))
{
     @Html.Hidden("StepType", currentStep.GetType())
     @Html.EditorFor(x => currentStep, null, "")

     <button type="submit">Submit</button>
}


您不必为此问题担心Model UserAddUpdate,它只包含一个IUserAddUpdateStep列表,但这是它的样子

 public class UserAddUpdate
    {
        public int CurrentStepIndex { get; set; }
        public IList<IUserAddUpdateStep> Steps { get; set; }

        public void Initialize()
        {
            Steps = typeof(IUserAddUpdateStep)
                .Assembly
                .GetTypes()
                .Where(t => !t.IsAbstract && typeof(IUserAddUpdateStep).IsAssignableFrom(t))
                .Select(t => (IUserAddUpdateStep)Activator.CreateInstance(t))
                .ToList();

        }
    }


对于特定步骤,@Html.EditorFor将加载与IUserAddUpdateStep类型的具体实现视图模型匹配的.cshtml编辑器模板。

此设置非常有效!

然后,我希望在实现IUserAddUpdateStep的所有视图模型之间共享一个公共值,我在IUserAddUpdateStep中添加了common属性:

public interface IUserAddUpdateStep
{
    string UserId { get; set; }
}


然后,我的视图模型继承自新的基本抽象类,而不是IUserAddUpdateStep

public abstract class UserAddUpdateStepBase: IUserAddUpdateStep
{
    public string UserId { get; set; }
}


然后,类型的具体具体实现视图模型如下所示:

public class UserAddUpdateOverview: UserAddUpdateStepBase
{
}


UserAddUpdateOverview仍为IUserAddUpdateStep类型,但现在继承自抽象基类UserAddUpdateStepBase

最后,我以自己的形式添加到了AddUpdate.cshtml视图中:

 <input type="hidden" id="UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>


除了UserId属性之外,其他所有东西都运行良好,当表单发布到我的控制器方法public ActionResult AddUpdate(IUserAddUpdateStep step)时,我无法进行反序列化。 UserId为空。

我可以使用DOM中的浏览器F12开发人员工具检查器查看隐藏的输入值,它是我<form />的子级:

c# - 如何获取ASP.NET MVC操作方法以解析在接口(interface)中定义并在Abstract类中实现的属性-LMLPHP

我也尝试过:

<input type="hidden" id="UserAddUpdateStepBase_UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>


和:

<input type="hidden" id="UserAddUpdateStepBase.UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>


和:

 <input type="hidden" id="IUserAddUpdateStep.UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>


和:

 <input type="hidden" id="IUserAddUpdateStep_UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>


目前,我的解决方案是删除抽象基类,并仅在类型为UserId的每个具体实现视图模型中实现IUserAddUpdateStep属性。但是,如果有人对我如何指导ASP.NET正确地反序列化隐藏的输入UserId(该ID映射到我的抽象类的信息)有很好的了解,这将使他们知道这是一个解决方案,那么对此进行解释。

最佳答案

您需要在name标记上添加input属性,以在帖子中发送该值。在您的情况下:

<input type="hidden" name="UserId" id="UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>

关于c# - 如何获取ASP.NET MVC操作方法以解析在接口(interface)中定义并在Abstract类中实现的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41045014/

10-12 05:55