gpt4 book ai didi

asp.net-mvc - MVC 动态 View 数据和动态 View

转载 作者:行者123 更新时间:2023-12-02 01:05:33 24 4
gpt4 key购买 nike

传统上,我使用具有数据注释属性的 View 模型构建 MVC 应用程序,并使用编辑器模板动态渲染 View 。一切都很顺利,它确实减少了我构建新 View 所需的时间。我的要求最近发生了变化。现在,我无法在设计时定义 View 模型。将在 View 上呈现的属性是在运行时根据业务规则决定的。此外,这些属性的验证规则也可以在运行时决定。 (在我的域模型中不需要的字段,根据业务规则在我看来可能是必需的)。此外,要渲染的属性集直到运行时才知道 - 用户 A 可以编辑模型中的 6 个属性,而用户 B 可以编辑 9 个属性。

我想知道是否可以创建一个模型元数据提供程序,该提供程序将根据业务规则为非类型化 View 模型(例如属性名称和值的集合)提供我自己的元数据。有人解决这个问题了吗?

最佳答案

我通过创建一个更复杂的模型解决了类似的问题,并使用自定义编辑器模板使模型呈现为看起来像典型的编辑器,但使用动态字段信息:

public class SingleRowFieldAnswerForm
{
/// <summary>
/// The fields answers to display.
/// This is a collection because we ask the MVC to bind parameters to it,
/// and it could cause issues if the underlying objects were being recreated
/// each time it got iterated over.
/// </summary>
public ICollection<IFieldAnswerModel> FieldAnswers { get; set; }
}

public interface IFieldAnswerModel
{
int FieldId { get; set; }

string FieldTitle { get; set; }

bool DisplayAsInput { get; }

bool IsRequired { get; }

bool HideSurroundingHtml { get; }
}

// sample implementation of IFieldAnswerModel
public class TextAreaFieldAnswer : FieldAnswerModelBase<TextAreaDisplayerOptions>
{
public string Answer { get; set; }
}

EditorTemplates/SingleRowFieldAnswerForm.cshtml:

@helper DisplayerOrEditor(IFieldAnswerModel answer)
{
var templateName = "FieldAnswers/" + answer.GetType().Name;
var htmlFieldName = string.Format("Answers[{0}]", answer.FieldId);

if (answer.DisplayAsInput)
{
@Html.EditorFor(m => answer, templateName, htmlFieldName)
// This will display validation messages that apply to the entire answer.
// This typically means that the input got past client-side validation and
// was caught on the server instead.
// Each answer's view must also produce a validation message for
// its individual properties if you want client-side validation to be
// enabled.
@Html.ValidationMessage(htmlFieldName)
}
else
{
@Html.DisplayFor(m => answer, templateName, htmlFieldName)
}
}
<div class="form-section">
<table class="form-table">
<tbody>
@{
foreach (var answer in Model.FieldAnswers)
{
if (answer.HideSurroundingHtml)
{
@DisplayerOrEditor(answer)
}
else
{
var labelClass = answer.IsRequired ? "form-label required" : "form-label";
<tr>
<td class="@labelClass">
@answer.FieldTitle:
</td>
<td class="form-field">
<div>
@DisplayerOrEditor(answer)
</div>
</td>
</tr>
}
}
}
</tbody>
</table>
</div>

因此,我用一系列答案模型填充我的 SingleRowFieldAnswerForm。每个答案模型类型都有自己的编辑器模板,允许我自定义不同类型的动态“属性”的显示方式。例如:

// EditorTemplates/FieldAnswers/TextAreaFieldAnswer.cshtml

@model TextAreaFieldAnswer

@{
var htmlAttributes = Html.GetUnobtrusiveValidationAttributes("Answer", ViewData.ModelMetadata);
// add custom classes that you want to apply to your inputs.
htmlAttributes.Add("class", "multi-line input-field");
}
@Html.TextAreaFor(m => m.Answer, Model.Options.Rows, 0, htmlAttributes)
@Html.ValidationMessage("Answer")

下一个棘手的部分是,当您将此信息发送到服务器时,它本身并不知道要构造哪种类型的 IFieldAnswerModel,因此您不能只绑定(bind) SingleRowAnswerForm 在你的参数列表中。相反,你必须做这样的事情:

public ActionResult SaveForm(int formId)
{
SingleRowAnswerForm form = GetForm(formId);
foreach (var fieldAnswerModel in form.FieldAnswers.Where(a => a.DisplayAsInput))
{
// Updating this as a dynamic makes sure all the properties are bound regardless
// of the runtime type (since UpdateModel relies on the generic type normally).
this.TryUpdateModel((dynamic) fieldAnswerModel,
string.Format("Answers[{1}]", fieldAnswerModel.FieldId));
}
...

由于您为 MVC 提供了要绑定(bind)的每个动态“属性”值,因此它可以毫无困难地绑定(bind)每个答案类型上的每个属性。

显然,我省略了很多细节,例如如何首先生成答案模型,但希望这能让您走上正轨。

关于asp.net-mvc - MVC 动态 View 数据和动态 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10837948/

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