加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – MVC 3.0编辑可变长度列表并使用PRG模式

发布时间:2020-12-16 09:35:08 所属栏目:asp.Net 来源:网络整理
导读:我创建了一个带有可变长度列表的视图,如下所述: http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/. 我正在尝试使用带有动作过滤器的PRG模式,如第13点所述:http://weblogs.asp.net/rashid/archive/2009/04/
我创建了一个带有可变长度列表的视图,如下所述: http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/.

我正在尝试使用带有动作过滤器的PRG模式,如第13点所述:http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx.

我有一个编辑动作:

[HttpGet,ImportModelStateFromTempData]
    public ActionResult Edit(int id)
    {
    }

和后期行动:

[HttpPost,ExportModelStateToTempData]
    public ActionResult Edit(int id,FormCollection formCollection)
    {
        if (!TryUpdateModel<CategoryEntity>(category,formCollection))
        {
            return RedirectToAction("Edit",new { id = id });
        }

        // succes,no problem processing this...
        return RedirectToAction("Edit",new { id = id });
    }

一切正常,包括验证和错误消息.

我唯一的问题是重定向后不保留新添加的项目和删除的项目(客户端删除/添加).我试图找到一种方法来重新定位新项目后更新我的模型.我更改了ImportModelStateFromTempData属性以使用OnActionExecuting覆盖而不是OnActionExecuted覆盖来使操作中的ModelState可用但我没有看到从传入的ModelState更新我的模型的干净方法.

更改了ImportModelStateFromTempData:

public class ImportModelStateFromTempData : ModelStateTempDataTransfer
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;

        if (modelState != null)
        {
            filterContext.Controller.ViewData.ModelState.Merge(modelState);
        }
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;

        //if (modelState != null)
        //{
        //    //Only Import if we are viewing
        //    if (filterContext.Result is ViewResult)
        //    {
        //        filterContext.Controller.ViewData.ModelState.Merge(modelState);
        //    }
        //    else
        //    {
        //        //Otherwise remove it.
        //        filterContext.Controller.TempData.Remove(Key);
        //    }
        //}
        base.OnActionExecuted(filterContext);
    }
}

对此有任何意见,非常感谢,谢谢.

Harmen

更新:我想我可能会添加更多我的(伪)代码以使其更清晰:

public class CategoryEntity
{
    public int Id;
    public string Name;
    public IEnumerable<CategoryLocEntity> Localized;
}

public class CategoryLocEntity
{
    public int CategoryId;
    public int LanguageId;
    public string LanguageName;
    public string Name;
}

我的编辑视图:

@model CategoryEntity

@{
    ViewBag.Title = Views.Category.Edit;
}

<h2>@Views.Category.Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript"><!--

    $(document).ready(function () {
        $('#addItem').click(function () {
            var languageId = $('#languageId').val();
            var index = $('#editor-rows').children().size() - 1;
            $.ajax({
                url: this.href + '?languageId=' + languageId + '&index=' + index,cache: false,error: function (xhr,status,error) {
                    alert(error);
                },success: function (html) {
                    $('#editor-rows').append(html);
                }
            });
            return false;
        });

        $("a.removeItem").live("click",function () {
            $(this).parents("div.editor-row:first").remove();
            return false;
        });
    });

--></script>

@using (Html.BeginForm()) 
{
    @Html.ValidationSummary(false)
    <fieldset>
        <legend>@Views.Shared.Category</legend>
        @Html.HiddenFor(model => model.Id)
        <div id="editor-rows">
            <div class="editor-row">
                <div class="editor-label">
                    @Html.LabelFor(model => model.Name,Views.Shared.NameEnglish)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Name)
                    @Html.ValidationMessageFor(model => model.Name)
                </div>
            </div>

            @for (int i = 0; i < Model.Localized.Count; i++)
            {
                @Html.EditorFor(m => m.Localized[i],"_CategoryLoc",null,null)
            }
        </div>

        <div class="editor-label"></div>
        <div class="editor-field">
            @Html.DropDownList("languageId",(IEnumerable<SelectListItem>)ViewBag.LanguageSelectList)
            @Html.ActionLink(Views.Category.AddNewLanguage,"AddNewLanguage",new { id = "addItem" })
        </div>

        <p class="clear">
            <input type="submit" value="@Views.Shared.Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink(Views.Shared.BackToList,"Index")
</div>

CategoryLocEntity的编辑器模板:

@model CategoryLocEntity

<div class="editor-row">
    @Html.HiddenFor(model => model.Id)
    @Html.HiddenFor(model => model.LanguageId)
    <div class="editor-label">
        @Html.LabelFor(model => model.LanguageName,Model.LanguageName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        <a href="#" class="removeItem">@Views.Shared.Remove</a>
        @Html.ValidationMessageFor(model => model.Name)
    </div>
</div>

解决方法

我找到了一个解决方案(可能不是最优雅的解决方案,但它对我有用).我创建了自己的ModelStateValueProvider以与UpdateModel一起使用.代码基于DictionaryValueProvider.见 http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System.Web/System/Web/Mvc/DictionaryValueProvider%601.cs.htm.

public class ModelStateValueProvider : IValueProvider
{
    HashSet<string> prefixes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
    ModelStateDictionary modelStateDictionary;

    public ModelStateValueProvider(ModelStateDictionary modelStateDictionary)
    {
        if (modelStateDictionary == null)
            throw new ArgumentNullException("modelStateDictionary");

        this.modelStateDictionary = modelStateDictionary;

        FindPrefixes();
    }

    private void FindPrefixes()
    {
        if (modelStateDictionary.Count > 0)
            prefixes.Add(string.Empty);

        foreach (var modelState in modelStateDictionary)
            prefixes.UnionWith(GetPrefixes(modelState.Key));
    }

    public bool ContainsPrefix(string prefix)
    {
        if (prefix == null)
        {
            throw new ArgumentNullException("prefix");
        }

        return prefixes.Contains(prefix);
    }

    public ValueProviderResult GetValue(string key)
    {
        if (key == null)
            throw new ArgumentNullException("key");

        return modelStateDictionary.ContainsKey(key) ? modelStateDictionary[key].Value : null;
    }

    static IEnumerable<string> GetPrefixes(string key)
    {
        yield return key;
        for (int i = key.Length - 1; i >= 0; i--)
        {
            switch (key[i])
            {
                case '.':
                case '[':
                    yield return key.Substring(0,i);
                    break;
            }
        }
    }
}

public class ModelStateValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        return new ModelStateValueProvider(controllerContext.Controller.ViewData.ModelState);
    }
}

我在de Edit(Get)动作中使用它,如:

[HttpGet,ImportModelStateFromTempData]
public ActionResult Edit(int id)
{
  var category = new CategoryEntity(id);
  if (!ModelState.IsValid)
  {    
     TryUpdateModel<CategoryEntity>(category,new ModelStateValueProviderFactory().GetValueProvider(ControllerContext));
  }
  return View(category);
}

期待您的评论……

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读