Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 每次使用新的guid索引时,如何获取要在集合属性上呈现的验证消息?_C#_Asp.net Mvc_Asp.net Mvc 4 - Fatal编程技术网

C# 每次使用新的guid索引时,如何获取要在集合属性上呈现的验证消息?

C# 每次使用新的guid索引时,如何获取要在集合属性上呈现的验证消息?,c#,asp.net-mvc,asp.net-mvc-4,C#,Asp.net Mvc,Asp.net Mvc 4,在这个ASP.NETMVC4程序的例子中,我让一个用户填写有关赛马的详细信息。这场比赛有一个名字,还有一份参赛马的名单。每匹马都有名字和年龄 表单使用ajax和javascript允许用户动态添加和删除输入字段,然后在按下submit按钮时一次提交 为了让这个过程对我来说更简单,我使用了made by public static MvcHtmlString EditorForMany(此HtmlHelper html,表达式,字符串htmlFieldName=null),其中TModel:cla

在这个ASP.NETMVC4程序的例子中,我让一个用户填写有关赛马的详细信息。这场比赛有一个名字,还有一份参赛马的名单。每匹马都有名字和年龄

表单使用ajax和javascript允许用户动态添加和删除输入字段,然后在按下submit按钮时一次提交

为了让这个过程对我来说更简单,我使用了made by

public static MvcHtmlString EditorForMany(此HtmlHelper html,表达式,字符串htmlFieldName=null),其中TModel:class
{
var items=expression.Compile()(html.ViewData.Model);
var sb=新的StringBuilder();
if(String.IsNullOrEmpty(htmlFieldName))
{
var prefix=html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
htmlFieldName=(prefix.Length>0?(prefix+):String.Empty)+ExpressionHelper.GetExpressionText(表达式);
}
foreach(项目中的var项目)
{
var dummy=new{Item=Item};
var guid=guid.NewGuid().ToString();
var memberExp=Expression.MakeMemberAccess(Expression.Constant(dummy)、dummy.GetType().GetProperty(“项”);
var singleItemExp=Expression.Lambda(memberExp,Expression.Parameters);
sb.Append(字符串格式(@“”,htmlFieldName,guid));
Append(html.EditorFor(singleItemExp,null,String.Format(“{0}[{1}]”,htmlFieldName,guid));
}
返回新的MvcHtmlString(sb.ToString());
}
虽然我不理解所有细节(请阅读博客文章),但我知道它将索引值更改为guid,而不是顺序整数。这允许我删除列表中间的项目,而不需要重新计算索引。

这是我的MCVE的其余代码

HomeController.cs

public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        var model = new Race();

        //start with one already filled in
        model.HorsesInRace.Add(new Horse() { Name = "Scooby", Age = 10 });

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(Race postedModel)
    {
        if (ModelState.IsValid)
            //model is valid, redirect to another page
            return RedirectToAction("ViewHorseListing");
        else
            //model is not valid, show the page again with validation errors
            return View(postedModel);
    }

    [HttpGet]
    public ActionResult AjaxMakeHorseEntry()
    {
        //new blank horse for ajax call
        var model = new List<Horse>() { new Horse() };
        return PartialView(model);
    }
}
公共类HomeController:控制器
{
[HttpGet]
公共行动结果索引()
{
var模型=新种族();
//从一个已经填好的开始
model.HorsesInRace.Add(newhorse(){Name=“Scooby”,Age=10});
返回视图(模型);
}
[HttpPost]
公共行动结果索引(种族postedModel)
{
if(ModelState.IsValid)
//模型有效,请重定向到其他页面
返回重定向到操作(“查看列表”);
其他的
//模型无效,请再次显示带有验证错误的页面
返回视图(postedModel);
}
[HttpGet]
公共行动结果AjaxMakeHorseEntry()
{
//用于ajax调用的新blank horse
var model=newlist(){newhorse()};
返回局部视图(模型);
}
}
模型.cs

public class Race
{
    public Race() { HorsesInRace = new List<Horse>(); }

    [Display(Name = "Race Name"), Required]
    public string RaceName { get; set; }

    [Display(Name = "Horses In Race")]
    public List<Horse> HorsesInRace { get; set; }
}

public class Horse
{
    [Display(Name = "Horse's Name"), Required]
    public string Name { get; set; }

    [Display(Name = "Horse's Age"), Required]
    public int Age { get; set; }
}
公共级比赛
{
public Race(){HorsesInRace=new List();}
[显示(名称=“比赛名称”),必填]
公共字符串名称{get;set;}
[显示(Name=“赛马”)]
公共列表horssinrace{get;set;}
}
公马
{
[显示(名称=“马名”),必填]
公共字符串名称{get;set;}
[显示(Name=“马龄”),必填]
公共整数{get;set;}
}
Index.cshtml

@model CollectionAjaxPosting.Models.Race
<h1>Race Details</h1>
@using (Html.BeginForm())
{
    @Html.ValidationSummary()
    <hr />
    <div>
        @Html.DisplayNameFor(x => x.RaceName)
        @Html.EditorFor(x => x.RaceName)
        @Html.ValidationMessageFor(x => x.RaceName)
    </div>
    <hr />
    <div id="horse-listing">@Html.EditorForMany(x => x.HorsesInRace)</div>
    <button id="btn-add-horse" type="button">Add New Horse</button>
    <input type="submit" value="Enter Horses" />
}

<script type="text/javascript">
    $(document).ready(function () {

        //add button logic
        $('#btn-add-horse').click(function () {
            $.ajax({
                url: '@Url.Action("AjaxMakeHorseEntry")',
                cache: false,
                method: 'GET',
                success: function (html) {
                    $('#horse-listing').append(html);
                }
            })
        });

        //delete-horse buttons
        $('#horse-listing').on('click', 'button.delete-horse', function () {
            var horseEntryToRemove = $(this).closest('div.horse');
            horseEntryToRemove.prev('input[type=hidden]').remove();
            horseEntryToRemove.remove();
        });

    });
</script>
@model collectionaaxposting.Models.Race
比赛详情
@使用(Html.BeginForm())
{
@Html.ValidationSummary()

@DisplayNameFor(x=>x.RaceName) @EditorFor(x=>x.RaceName) @Html.ValidationMessageFor(x=>x.RaceName)
@EditorForMany(x=>x.HorsesInRace) 添加新马 } $(文档).ready(函数(){ //添加按钮逻辑 $(“#btn添加马”)。单击(函数(){ $.ajax({ url:'@url.Action(“AjaxMakeHorseEntry”), cache:false, 方法:“GET”, 成功:函数(html){ $(“#马列表”).append(html); } }) }); //删除骑马按钮 $(“#马列表”)。在('click','button.delete horse',函数(){ var horseEntryToRemove=$(this.closest('div.horse'); horsentrytoremove.prev('input[type=hidden]').remove(); horsentrytoremove.remove(); }); });
Views/Shared/EditorTemplates/Horse.cshtml

@model CollectionAjaxPosting.Models.Horse

<div class="horse">
    <div>
        @Html.DisplayNameFor(x => x.Name)
        @Html.EditorFor(x => x.Name)
        @Html.ValidationMessageFor(x => x.Name)
    </div>
    <div>
        @Html.DisplayNameFor(x => x.Age)
        @Html.EditorFor(x => x.Age)
        @Html.ValidationMessageFor(x => x.Age)
    </div>
    <button type="button" class="delete-horse">Remove Horse</button>
    <hr />
</div>
@model collection.Models.Horse
@DisplayNameFor(x=>x.Name)
@EditorFor(x=>x.Name)
@Html.ValidationMessageFor(x=>x.Name)
@DisplayNameFor(x=>x.Age)
@EditorFor(x=>x.Age)
@Html.ValidationMessageFor(x=>x.Age)
脱马

Views/Home/ajaxmakehorsentry.cshtml

@model IEnumerable<CollectionAjaxPosting.Models.Horse>

@Html.EditorForMany(x => x, "HorsesInRace")
@model IEnumerable
@EditorForMany(x=>x,“HorsesInRace”)
数据流使用此代码。一个人可以在页面上创建和删除任意多的条目,并且当表单提交时,所有输入的值都会被提供给action方法

但是,如果用户没有在马条目的
[必需]
信息中输入,
ModelState.IsValid
将为false,再次显示表单,但是不会显示马属性的验证消息。不过,验证错误确实显示在
ValidationSummary
列表中

例如,如果
比赛名称
留空,同时显示一匹
马的名称
,将显示前一匹的验证消息。后者将使用类“field validation valid”进行验证

我很确定这是因为每次创建页面时,
EditorForMany
方法都会为每个属性创建新的guid,因此验证消息无法匹配到正确的字段

我能做些什么来解决这个问题?我是否需要放弃guid索引创建,或者是否可以更改
EditorForMany
方法以允许验证消息
@model IEnumerable<CollectionAjaxPosting.Models.Horse>

@Html.EditorForMany(x => x, "HorsesInRace")
public static class HtmlHelperExtensions
{
    public static MvcHtmlString EditorForMany<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TValue>>> propertyExpression, Expression<Func<TValue, string>> indexResolverExpression = null, string htmlFieldName = null) where TModel : class
    {
        htmlFieldName = htmlFieldName ?? ExpressionHelper.GetExpressionText(propertyExpression);

        var items = propertyExpression.Compile()(html.ViewData.Model);
        var htmlBuilder = new StringBuilder();
        var htmlFieldNameWithPrefix = html.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName);
        Func<TValue, string> indexResolver = null;

        if (indexResolverExpression == null)
        {
            indexResolver = x => null;
        }
        else
        {
            indexResolver = indexResolverExpression.Compile();
        }

        foreach (var item in items)
        {
            var dummy = new { Item = item };
            var guid = indexResolver(item);
            var memberExp = Expression.MakeMemberAccess(Expression.Constant(dummy), dummy.GetType().GetProperty("Item"));
            var singleItemExp = Expression.Lambda<Func<TModel, TValue>>(memberExp, propertyExpression.Parameters);

            if (String.IsNullOrEmpty(guid))
            {
                guid = Guid.NewGuid().ToString();
            }
            else
            {
                guid = html.AttributeEncode(guid);
            }

            htmlBuilder.Append(String.Format(@"<input type=""hidden"" name=""{0}.Index"" value=""{1}"" />", htmlFieldNameWithPrefix, guid));

            if (indexResolverExpression != null)
            {
                htmlBuilder.Append(String.Format(@"<input type=""hidden"" name=""{0}[{1}].{2}"" value=""{1}"" />", htmlFieldNameWithPrefix, guid, ExpressionHelper.GetExpressionText(indexResolverExpression)));
            }

            htmlBuilder.Append(html.EditorFor(singleItemExp, null, String.Format("{0}[{1}]", htmlFieldName, guid)));
        }

        return new MvcHtmlString(htmlBuilder.ToString());
    }
}
public class Race
{
    public Race() { HorsesInRace = new List<Horse>(); }

    [Display(Name = "Race Name"), Required]
    public string RaceName { get; set; }

    [Display(Name = "Horses In Race")]
    public List<Horse> HorsesInRace { get; set; }
}

public class Horse
{
    [Display(Name = "Horse's Name"), Required]
    public string Name { get; set; }

    [Display(Name = "Horse's Age"), Required]
    public int Age { get; set; }

    // Note the addition of Index here.
    public string Index { get; set; }
}    
<div id="horse-listing">@Html.EditorForMany(x => x.HorsesInRace, x => x.Index)</div>
@Html.EditorForMany(x => x, x => x.Index, "HorsesInRace")
[HttpGet]
public ActionResult AjaxMakeHorseEntry()
{
    var model = new Race();

    model.HorsesInRace.Add(new Horse());
    return PartialView(model);
}
@model Models.Race

@Html.EditorForMany(x => x.HorsesInRace, x => x.Index)