Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.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/3/html/71.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# 第一次发布后,隐藏字段的值错误_C#_Html_Asp.net Mvc - Fatal编程技术网

C# 第一次发布后,隐藏字段的值错误

C# 第一次发布后,隐藏字段的值错误,c#,html,asp.net-mvc,C#,Html,Asp.net Mvc,我有一个视图,用户可以使用HTML表单记录在活动上花费的时间。因此,该视图循环遍历所有活动的列表,并为每个活动生成一个日志时间表单(包含在_LogTime部分视图中)。从索引视图传递到局部视图的唯一信息是ActivityId,它以隐藏形式放置。其余所需信息由用户通过提供 我遇到的问题是,一旦我提交了其中一个表单,所有表单的隐藏字段都设置为我刚刚提交的表单的ActivityId。值得注意的是,当页面第一次加载时(在我提交任何表单之前),隐藏字段是正确的,当我第一次提交表单时,正确的活动会被记录时间

我有一个视图,用户可以使用HTML表单记录在活动上花费的时间。因此,该视图循环遍历所有活动的列表,并为每个活动生成一个日志时间表单(包含在_LogTime部分视图中)。从索引视图传递到局部视图的唯一信息是ActivityId,它以隐藏形式放置。其余所需信息由用户通过提供

我遇到的问题是,一旦我提交了其中一个表单,所有表单的隐藏字段都设置为我刚刚提交的表单的ActivityId。值得注意的是,当页面第一次加载时(在我提交任何表单之前),隐藏字段是正确的,当我第一次提交表单时,正确的活动会被记录时间(其他活动都不会错误地记录时间)。但之后的任何表单提交都只会记录我第一次提交表单的活动的时间

知道这是怎么回事吗?为什么所有隐藏字段都设置为相同的ActivityId?为什么只有在第一篇文章之后?如果您需要任何问题的澄清,请告诉我

型号:

public class Activity
{
    public int ActivityId { get; set; }
    public string Name { get; set; }
}

public class UserActivity
{
    public int UserId { get; set; }
    public int ActivityId { get; set; }
    public int Duration { get; set; }
    public DateTime Date { get; set; }
}
观点:

// Index View
@foreach (Activity activity in Model)
{
    @Html.Partial("_LogTime", new UserActivity(activity.ActivityId))
}

// _LogTime Partial View
@using (Html.BeginForm())
{
    <fieldset>
        @Html.HiddenFor(model => model.ActivityId)
        @Html.EditorFor(model => model.Duration)
        @Html.EditorFor(model => model.Date)

        <input type="submit" value="LOG TIME" />
    </fieldset>
}

我从不在控制器中使用全局变量。 我宁愿把我所有隐藏的值,也包括foreach局部视图中的值,都放在表单中

这样,您可以传递整个列表,然后再添加一个。 现在,我认为您传递了一个空行,并将最后一个添加到该行

当然,可以在post函数中设置断点

@using (Html.BeginForm())
{
    // Index View
    @foreach (Activity activity in Model)
    {
        @Html.Partial("_LogTime", new UserActivity(activity.ActivityId))
    }

    // _LogTime Partial View

    <fieldset>
        @Html.HiddenFor(model => model.ActivityId)
        @Html.EditorFor(model => model.Duration)
        @Html.EditorFor(model => model.Date)

        <input type="submit" value="LOG TIME" />
    </fieldset>
}
@使用(Html.BeginForm())
{
//索引视图
@foreach(模型中的活动)
{
@Html.Partial(“_LogTime”,新用户活动(activity.ActivityId))
}
//_LogTime局部视图
@Html.HiddenFor(model=>model.ActivityId)
@EditorFor(model=>model.Duration)
@EditorFor(model=>model.Date)
}

您遇到的问题是,html助手方法会自动使用同名的post变量更新表单元素。这些值存储在ModelState中。解决此问题的一种方法是从ModelState中删除有问题的条目

另一个可能的修复方法是改为重定向

[HttpPost]
public ActionResult Index(UserActivity activity)
{
    if (ModelState.IsValid)
    {
        _db.UserActivities.Add(activity);
        _db.SaveChanges();
    }

    // Remove the ActivityId from your ModelState before returning the View.
    ModelState.Remove("ActivityId")

    return View(_db.Activities.ToList());
}
从下面的注释可以看出,使用Remove方法可能表明应用程序的流程存在更深层的问题。在这一点上,我同意埃里克的观点。正如他所指出的,重新设计应用程序的流程可能是一项耗时的任务

当遇到问题指示的行为时,如果有一种方法可以在不修改ModelState的情况下解决问题,那么这将是首选的解决方案。一个恰当的例子可能是不止一个元素受到此问题的影响

为了完整起见,这里有一个替代解决方案:

[HttpPost]
public ActionResult Index(UserActivity activity)
{
    if (ModelState.IsValid)
    {
        _db.UserActivities.Add(activity);
        _db.SaveChanges();
    }

    return RedirectToAction("Index");
}
在让我的批评者闭嘴的最后,这是他无法想出的改写

// Index View
@using (Html.BeginForm())
{

    @for (var i = 0; i < Model.Count; i++)
    {
        <div>
            @Html.HiddenFor(model => model[i].ActivityId)
            @Html.EditorFor(model => model[i].Duration)
            @Html.EditorFor(model => model[i].Date)
        </div>
    }
    <input type="submit" value="LOG TIME ENTRIES" />

}

// Controller Post Method
[HttpPost]
public ActionResult Index(List<UserActivity> activities)
{
    if (ModelState.IsValid)
    {
        foreach( var activity in activities ) 
        {
            var first = _db.UserActivities
                  .FirstOrDefault(row => row.ActivityId == activity.ActivityId );
            if ( first == null ) {
               _db.UserActivities.Add(activity);
            } else {
               first.Duration = activity.Duration;
               first.Date = activity.Date;
            }
        }
        _db.SaveChanges();

        return RedirectToAction("index");
    }

    // when the ModelState is invalid, we want to 
    // retain posted values and display errors.
    return View(_db.Activities.ToList());
}
//索引视图
@使用(Html.BeginForm())
{
@对于(var i=0;imodel[i].ActivityId)
@EditorFor(model=>model[i].Duration)
@Html.EditorFor(model=>model[i].Date)
}
}
//控制岗位法
[HttpPost]
公共行动结果索引(列出活动)
{
if(ModelState.IsValid)
{
foreach(活动中的var活动)
{
var first=_db.UserActivities
.FirstOrDefault(行=>row.ActivityId==activity.ActivityId);
if(first==null){
_db.UserActivities.Add(活动);
}否则{
first.Duration=活动.Duration;
first.Date=activity.Date;
}
}
_db.SaveChanges();
返回操作(“索引”);
}
//当ModelState无效时,我们希望
//保留发布的值并显示错误。
返回视图(_db.Activities.ToList());
}

在发布这样的代码块时,请添加解释。不是真的,这只是代码,请解释您所做的更改以及原因。@erik我不同意。假设你有一个更好的答案,而不是投反对票。在请求的编辑中,我还提到了另一个选项。@B2K-您可以随意不同意,这不会改变他的代码将生成无效html(具有相同ID的多个项目)的事实。你只是在治疗症状。解决这个问题需要完全重写他的代码,我不打算这么做。您不必从ModelState中删除项。如果你是,那么这是一个不同问题的症状,你只是在掩盖它。修复真正的问题。@ErikFunkenbusch请告诉我,如果Microsoft从未打算使用Remove方法,为什么要在ModelState中添加Remove方法。它们还提供ModelState.Clear命令。这两种方法都不推荐。它们可以在应用程序需要时使用。
// Index View
@using (Html.BeginForm())
{

    @for (var i = 0; i < Model.Count; i++)
    {
        <div>
            @Html.HiddenFor(model => model[i].ActivityId)
            @Html.EditorFor(model => model[i].Duration)
            @Html.EditorFor(model => model[i].Date)
        </div>
    }
    <input type="submit" value="LOG TIME ENTRIES" />

}

// Controller Post Method
[HttpPost]
public ActionResult Index(List<UserActivity> activities)
{
    if (ModelState.IsValid)
    {
        foreach( var activity in activities ) 
        {
            var first = _db.UserActivities
                  .FirstOrDefault(row => row.ActivityId == activity.ActivityId );
            if ( first == null ) {
               _db.UserActivities.Add(activity);
            } else {
               first.Duration = activity.Duration;
               first.Date = activity.Date;
            }
        }
        _db.SaveChanges();

        return RedirectToAction("index");
    }

    // when the ModelState is invalid, we want to 
    // retain posted values and display errors.
    return View(_db.Activities.ToList());
}