Asp.net mvc 3 MVC3定制HTMLHelper、局部视图或其他应用干燥原理的解决方案

Asp.net mvc 3 MVC3定制HTMLHelper、局部视图或其他应用干燥原理的解决方案,asp.net-mvc-3,razor,Asp.net Mvc 3,Razor,我有一个MVC3只读视图,其中包含一个显示项目属性的表 对于项目的许多属性,我们跟踪供应商对项目所做的更改。因此,例如,供应商可能会将名为“Color”的属性值从“Blue”更新为“Red”。在此视图中,表列出了表行中跟踪的每个属性,其中一列显示“旧值”和“新值”。下一列显示当前更改的状态(等待批准、已批准或已拒绝)。但是,对于管理员用户,该列将包含链接(“批准”、“拒绝”或“重置为等待批准”) 我为此编写的标记和Razor代码非常重复,而且难以控制。我想为此创建一个HTMLHelper,或者可

我有一个MVC3只读视图,其中包含一个显示项目属性的表

对于项目的许多属性,我们跟踪供应商对项目所做的更改。因此,例如,供应商可能会将名为“Color”的属性值从“Blue”更新为“Red”。在此视图中,表列出了表行中跟踪的每个属性,其中一列显示“旧值”和“新值”。下一列显示当前更改的状态(等待批准、已批准或已拒绝)。但是,对于管理员用户,该列将包含链接(“批准”、“拒绝”或“重置为等待批准”)

我为此编写的标记和Razor代码非常重复,而且难以控制。我想为此创建一个HTMLHelper,或者可能创建一个局部视图,我可以使用该视图将所有代码移动到其中,然后将其用于每个Item属性

下面是一个用于一个属性的代码示例。对于另外10个左右的属性,重复此代码

我正在使用一些jquery和ajax进行操作。例如,当拒绝更改时,用户必须输入拒绝更改的原因

    <tr id="rowId-color">
        <td>@Html.LabelFor(model => model.Color)</td>
        <td>@Html.DisplayFor(model => model.Color)</td>
        @if (Model.ChangeLog != null && Model.ChangeLog.Item("Color") != null) {
            var change = Model.ChangeLog.Item("Color");
            var changeStatus = (ItemEnumerations.ItemChangeStatuses)change.ItemChangeStatusID;
            <td>@change.OldValueDisplay</td>
            <td id="tdstatusId-@change.ItemChangeID">                                                                                
                @if (changeStatus == ItemEnumerations.ItemChangeStatuses.AwaitingApproval && User.IsInRole("TVAPMgr")) {
                                            @Ajax.ActionLink("Approve", "Approve", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Approve this change?", OnSuccess = "actionCompleted" })
                                            @Html.Raw("|")
                                            <a href="#dialog" name="reject" data-id="@change.ItemChangeID" >Reject</a>
                }
                else if ((changeStatus == ItemEnumerations.ItemChangeStatuses.Rejected || changeStatus == ItemEnumerations.ItemChangeStatuses.Approved) && User.IsInRole("TVAPMgr")) { 
                    @Ajax.ActionLink("Reset to Awaiting Approval", "Reset", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Reset this change to Awaiting Approval?", OnSuccess = "actionCompleted" })
                }
                else {
                    @changeStatus.ToDisplayString()
                }
            </td> 
            <td  id="tdreasonId-@change.ItemChangeID">@Html.DisplayFor(m => m.ChangeLog.Item(change.ItemChangeID).RejectedReason)</td>
        }
        else {
            <td colspan="3">No Change</td>
        }
    </tr>

@LabelFor(model=>model.Color)
@DisplayFor(model=>model.Color)
@if(Model.ChangeLog!=null&&Model.ChangeLog.Item(“颜色”)!=null){
var change=Model.ChangeLog.Item(“颜色”);
var changeStatus=(ItemEnumerations.ItemChangeStatuses)change.ItemChangeStatusID;
@change.OldValueDisplay
@if(changeStatus==ItemEnumerations.ItemChangeStatuses.WaitingApproval&&User.IsInRole(“TVAPMgr”)){
@ActionLink(“批准”、“批准”,新建{itemChangeID=change.itemChangeID},新建AjaxOptions{HttpMethod=“POST”,Confirm=“批准此更改?”,OnSuccess=“actionCompleted”})
@Html.Raw(“|”)文件
}
如果((changeStatus==ItemEnumerations.ItemChangeStatuses.Rejected | | changeStatus==ItemEnumerations.ItemChangeStatuses.Approved)&&User.IsInRole(“TVAPMgr”){
@ActionLink(“重置为等待批准”,“重置”,新建{itemChangeID=change.itemChangeID},新建AjaxOptions{HttpMethod=“POST”,Confirm=“重置此更改为等待批准?”,OnSuccess=“actionCompleted”})
}
否则{
@changeStatus.ToDisplayString()
}
@DisplayFor(m=>m.ChangeLog.Item(change.ItemChangeID.RejectedReason)
}
否则{
不变
}

这听起来更像是
ItemChangeModel
类型的显示模板,这样您就可以:

 <tr id="rowId-color">
    <td>@Html.LabelFor(model => model.Color)</td>
    <td>@Html.DisplayFor(model => model.Color)</td>
    @Html.DisplayFor(m => m.ChangeLog.Item("Color"))
</tr>
(很难在编辑器框中编码,这可能需要一些清理,但我想你会明白的)

您将此显示模板(文件名为ItemChangeModel.cshtml)添加到Views\Shared\DisplayTemplates文件夹中,每当对该类型进行DisplayFor调用时,都将使用该模板

注释中指出,您不能在DisplayFor中使用方法,但可以将其更改为索引属性:

public class ChangeLog
{
    public ItemChangeModel this[string key] { get { return Item("Color"); } }
}
然后使用:

@Html.DisplayFor(m => m.ChangeLog["Color"])

您没有显示或解释域和视图模型的外观,但我怀疑您在这里使用的视图模型不适合视图的这种特定需求。更好的视图模型应该是具有要批准的属性列表的模型,这些属性列表将显示在表中

无论如何,一种可能的方法是编写一个自定义HTML帮助程序,使您的视图如下所示:

@model ItemChangeModel

@if(Model != null) {

<td>@Html.DisplayFor(m => m.OldValueDisplay)</td>
<td id="tdstatusId-@Model.ItemChangeID">

@switch((ItemEnumerations.ItemChangeStatuses) Model.ItemChangeStatusID) {

    case ItemEnumerations.ItemChangeStatuses.AwaitingApproval:
        if(User.IsInRole("TVAPMgr")) {

            @Ajax.ActionLink("Approve", "Approve", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Approve this change?", OnSuccess = "actionCompleted" })

            @Html.Raw("|")

            <a href="#dialog" name="reject" data-id="@change.ItemChangeID" >Reject</a>

        }
        break;

    case ItemEnumerations.ItemChangeStatuses.Rejected:
    case ItemEnumerations.ItemChangeStatuses.Approved:

        if(User.IsInRole("TVAPMgr")) { 
                @Ajax.ActionLink("Reset to Awaiting Approval", "Reset", new { itemChangeID = change.ItemChangeID }, new AjaxOptions { HttpMethod = "POST", Confirm = "Reset this change to Awaiting Approval?", OnSuccess = "actionCompleted" })
        } else {
                @changeStatus.ToDisplayString()
        }

        @break;
 }

  </td> 
  <td  id="tdreasonId-@change.ItemChangeID">@Html.DisplayFor(m => m.RejectedReason)          </td>
} else {
    <td colspan="3">No Change</td>
}
<tr id="rowId-color">
    @Html.DisplayFor(x => x.Color)
    @Html.ChangeLogFor(x => x.Color)
</tr>
...

@DisplayFor(x=>x.Color)
@ChangeLogFor(x=>x.Color)
...
而助手可能是以下几点:

public static class HtmlExtensions
{
    public static IHtmlString ChangeLogFor<TProperty>(
        this HtmlHelper<MyViewModel> html, 
        Expression<Func<MyViewModel, TProperty>> ex
    )
    {
        var model = html.ViewData.Model;
        var itemName = ((MemberExpression)ex.Body).Member.Name;
        var change = model.ChangeLog.Item(itemName);
        if (change == null)
        {
            return new HtmlString("<td colspan=\"3\">No Change</td>");
        }

        var isUserTVAPMgr = html.ViewContext.HttpContext.User.IsInRole("TVAPMgr");
        var changeStatus = (ItemChangeStatuses)change.ItemChangeStatusID;

        var sb = new StringBuilder();
        sb.AppendFormat("<td>{0}</td>", html.Encode(change.OldValueDisplay));
        sb.AppendFormat("<td id=\"tdstatusId-{0}\">", change.ItemChangeID);
        var ajax = new AjaxHelper<MyViewModel>(html.ViewContext, html.ViewDataContainer);
        if (changeStatus == ItemChangeStatuses.AwaitingApproval && isUserTVAPMgr)
        {
            sb.Append(
                ajax.ActionLink(
                    "Approve", 
                    "Approve", 
                    new { 
                        itemChangeID = change.ItemChangeID 
                    }, 
                    new AjaxOptions { 
                        HttpMethod = "POST", 
                        Confirm = "Approve this change?", 
                        OnSuccess = "actionCompleted" 
                }).ToHtmlString()
            );
            sb.Append("|");
            sb.AppendFormat("<a href=\"#dialog\" name=\"reject\" data-id=\"{0}\">Reject</a>", change.ItemChangeID);
        }
        else if ((changeStatus == ItemChangeStatuses.Rejected || changeStatus == ItemChangeStatuses.Approved) && isUserTVAPMgr)
        {
            sb.Append(
                ajax.ActionLink(
                    "Reset to Awaiting Approval", 
                    "Reset", 
                    new { 
                        itemChangeID = change.ItemChangeID 
                    }, 
                    new AjaxOptions { 
                        HttpMethod = "POST", 
                        Confirm = "Reset this change to Awaiting Approval?", 
                        OnSuccess = "actionCompleted" 
                    }
                ).ToHtmlString()
            );
        }
        else
        {
            sb.Append(changeStatus.ToDisplayString());
        }

        sb.AppendLine("</td>");
        sb.AppendFormat(
            "<td id=\"tdreasonId-{0}\">{1}</td>", 
            change.ItemChangeID, 
            html.Encode(model.ChangeLog.Item(change.ItemChangeID).RejectedReason)
        );
        return new HtmlString(sb.ToString());
    }
}
public静态类
{
公共静态IHtmlString ChangeLogFor(
这个HtmlHelper html,
表达式ex
)
{
var model=html.ViewData.model;
var itemName=((MemberExpression)ex.Body).Member.Name;
var change=model.ChangeLog.Item(itemName);
if(change==null)
{
返回新的HtmlString(“无更改”);
}
var isUserTVAPMgr=html.ViewContext.HttpContext.User.IsInRole(“TVAPMgr”);
var changeStatus=(ItemChangeStatuses)change.ItemChangeStatusID;
var sb=新的StringBuilder();
sb.AppendFormat(“{0}”,html.Encode(change.OldValueDisplay));
sb.AppendFormat(“,change.ItemChangeID”);
var ajax=新的AjaxHelper(html.ViewContext、html.ViewDataContainer);
if(changeStatus==ItemChangeStatuses.waitingApproval&&isUserTVAPMgr)
{
附加(
ajax.ActionLink(
“批准”,
“批准”,
新{
itemChangeID=change.itemChangeID
}, 
新的AjaxOptions{
HttpMethod=“POST”,
确认=“批准此更改?”,
OnSuccess=“actionCompleted”
}).ToHtmlString()
);
某人加上(“|”);
sb.AppendFormat(“,change.ItemChangeID”);
}
else if((changeStatus==项目变更状态。已拒绝| |变更状态==项目变更状态。已批准)和&isUserTVAPMgr)
{
附加(
ajax.ActionLink(
“重置为等待批准”,
“重置”,
新{
itemChangeID=change.itemChangeID
}, 
新的AjaxOptions{
HttpMethod=“POST”,
确认=“将此更改重置为等待批准