我有一个包含 5 个步骤的向导,每个步骤都有一个实现 IUserAddUpdateStep
的 View 模型Interface
.
我的 Controller 中的操作方法如下所示
[HttpPost]
public ActionResult AddUpdate(IUserAddUpdateStep step)
还有一个 DefaultModelBinder
覆盖让 ASP.NET 知道如何处理 IUserAddUpdateStep
并获取上述 Controller 操作方法的 HTTP post 反序列化的具体类型,AddUpdate
:
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;
}
}
我发布了“IUserAddStep”类型的 View 模型,就像在我的 AddUpdate.cshtml
中一样查看:
@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
,对于特定步骤,将加载一个 .cshtml 编辑器模板,该模板与类型为 IUserAddUpdateStep
的具体实现 View 模型相匹配.
此设置一切正常!
然后我希望在所有实现 IUserAddUpdateStep
的 View 模型之间共享一个公共(public)值我将公共(public)属性添加到 IUserAddUpdateStep
:
public interface IUserAddUpdateStep
{
string UserId { get; set; }
}
然后我的 View 模型继承自一个新的抽象基类而不是 IUserAddUpdateStep
:
public abstract class UserAddUpdateStepBase: IUserAddUpdateStep
{
public string UserId { get; set; }
}
然后具体具体实现View Models类型是这样的:
public class UserAddUpdateOverview: UserAddUpdateStepBase
{
}
UserAddUpdateOverview 的类型仍然是 IUserAddUpdateStep
但现在继承自抽象基类UserAddUpdateStepBase
.
最后我添加到我的 AddUpdate.cshtml View ,当然是我的形式:
<input type="hidden" id="UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>
除了 UserId
之外,一切仍然正常属性,当表单发布到我的 Controller 方法时,我无法反序列化 public ActionResult AddUpdate(IUserAddUpdateStep step)
. UserId
为空。
我可以在 DOM 中使用浏览器 F12 Developer Tools Inspector 查看隐藏的输入值,它是我的 <form />
的子项:
我也试过:
<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
每个具体实现中的属性 View 模型类型 IUserAddUpdateStep
.但是,如果有人对我如何指导 ASP.NET 正确反序列化映射到我的抽象类的隐藏输入 UserId 有解释,那么知道他们是否是一个解决方案会很棒。
最佳答案
您需要在 input
标签上添加 name
属性以在帖子中发送值。在你的情况下:
<input type="hidden" name="UserId" id="UserId" value="@(((UserAddUpdateStepBase) currentStep).UserId)"/>
关于c# - 如何获取 ASP.NET MVC 操作方法来解析在接口(interface)中定义并在抽象类中实现的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41045014/