gpt4 book ai didi

asp.net-mvc-3 - MVC3 EditorFor 动态属性(或需要解决方法)

转载 作者:行者123 更新时间:2023-12-05 00:37:36 25 4
gpt4 key购买 nike

我正在建立一个提出问题并接收答案的系统。每个问题都可以有自己类型的答案。让我们将其限制为 StringDateTime目前。在域中,问题以下列方式表示:

public class Question
{
public int Id
{
get;
set;
}

public string Caption
{
get;
set;
}

public AnswerType
{
get;
set;
}
}

, 其中 AnswerType
enum AnswerType
{
String,
DateTime
}

请注意,实际上我有更多的答案类型。

我想出了一个创建 MVC 模型的想法,从 Question 派生并为其添加 Answer 属性。所以它必须是这样的:
public class QuestionWithAnswer<TAnswer> : Question
{
public TAnswer Answer
{
get;
set;
}
}

从这里开始问题。我想有一个通用的 View 来绘制任何问题,所以它需要是这样的:
@model QuestionWithAnswer<dynamic>

<span>@Model.Caption</span>
@Html.EditorFor(m => m.Answer)

对于 String我想在这里有简单的输入,对于 DateTime我要定义我自己的观点。我可以从 Controller 传递具体模型。但问题是,在渲染阶段,自然无法确定Answer的类型,尤其是如果最初是 null (默认为 String ),所以 EditorForString 绘制任何内容和 DateTime 中所有属性的输入.

我确实理解问题的本质,但有什么优雅的解决方法吗?或者我必须实现自己的逻辑来根据控件类型选择编辑器 View 名称(大丑 switch )?

最佳答案

我个人不喜欢这样:

enum AnswerType
{
String,
DateTime
}

我更喜欢使用 .NET 类型系统。让我建议你另一种设计。与往常一样,我们从定义 View 模型开始:
public abstract class AnswerViewModel
{
public string Type
{
get { return GetType().FullName; }
}
}

public class StringAnswer : AnswerViewModel
{
[Required]
public string Value { get; set; }
}

public class DateAnswer : AnswerViewModel
{
[Required]
public DateTime? Value { get; set; }
}

public class QuestionViewModel
{
public int Id { get; set; }
public string Caption { get; set; }
public AnswerViewModel Answer { get; set; }
}

然后是 Controller :
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new QuestionViewModel
{
Id = 1,
Caption = "What is your favorite color?",
Answer = new StringAnswer()
},
new QuestionViewModel
{
Id = 1,
Caption = "What is your birth date?",
Answer = new DateAnswer()
},
};
return View(model);
}

[HttpPost]
public ActionResult Index(IEnumerable<QuestionViewModel> questions)
{
// process the answers. Thanks to our custom model binder
// (see below) here you will get the model properly populated
...
}
}

然后是主要的 Index.cshtml看法:
@model QuestionViewModel[]

@using (Html.BeginForm())
{
<ul>
@for (int i = 0; i < Model.Length; i++)
{
@Html.HiddenFor(x => x[i].Answer.Type)
@Html.HiddenFor(x => x[i].Id)
<li>
@Html.DisplayFor(x => x[i].Caption)
@Html.EditorFor(x => x[i].Answer)
</li>
}
</ul>
<input type="submit" value="OK" />
}

现在我们可以为我们的答案提供编辑器模板:
~/Views/Home/EditorTemplates/StringAnswer.cshtml :
@model StringAnswer

<div>It's a string answer</div>
@Html.EditorFor(x => x.Value)
@Html.ValidationMessageFor(x => x.Value)
~/Views/Home/EditorTemplates/DateAnswer.cshtml :
@model DateAnswer

<div>It's a date answer</div>
@Html.EditorFor(x => x.Value)
@Html.ValidationMessageFor(x => x.Value)

最后一 block 是我们答案的自定义模型绑定(bind)器:
public class AnswerModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Type");
var type = Type.GetType(typeValue.AttemptedValue, true);
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}

将在 Application_Start 中注册:
ModelBinders.Binders.Add(typeof(AnswerViewModel), new AnswerModelBinder());

关于asp.net-mvc-3 - MVC3 EditorFor 动态属性(或需要解决方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6623577/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com