将模型绑定到视图存在的问题

3
尝试将模型绑定到视图时,出现了404错误。ActionResult称为'SortDesc',但视图只是一个标准的'Index'视图。我明白这是因为没有名为'SortDesc'的视图而无法加载。然而,我有两个按钮,一个用于升序排序数据,另一个用于降序排序数据,因此有两个单独的函数。我不确定在这里最好的解决方案是什么,是继续使用这两个单独的函数并以某种方式传递正确的视图以进行加载,还是在Index上创建一个新的、单独的HttpPost函数,它将知道哪个按钮已被单击并相应地排序。以下是我目前拥有的代码:
模型:
public class NumberSetList
{
    public int NumberSetListId { get; set; }
    public List<NumberList> Numbers { get; set; }

    public string SortOrder { get; set; }
}

public class NumberList
{
    public int NumberListId { get; set; } 
    public int Number1 { get; set; }
    public int Number2 { get; set; }
    public int Number3 { get; set; }
    public int Number4 { get; set; }
    public int Number5 { get; set; }
    public string SortOrder { get; set; }
}

Razor:

@{
    ViewBag.Title = "csi media web test";
}

<div class="jumbotron">
    <h1>csi media web test</h1>
    <p class="lead">Liane Stevenson</p>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="panel panel-info">
            <div class="panel-heading"><i class="glyphicon glyphicon-arrow-right"></i> Enter Your Four Numbers</div>
            <div class="panel-body">
                <form class="form-inline">
                    <div class="col-md-9">
                        <div class="form-group">
                            <label class="sr-only" for="number1">1st Number</label>
                            <input type="number" class="form-control" id="number1" name="Number1" placeholder="#1">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number2">2nd Number</label>
                            <input type="number" class="form-control" id="number2" name="Number2" placeholder="#2">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number3">3rd Number</label>
                            <input type="number" class="form-control" id="number3" name="Number3" placeholder="#3">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number4">4th Number</label>
                            <input type="number" class="form-control" id="number4" name="Number4" placeholder="#4">
                        </div>
                    </div>
                    <div class="col-md-3 text-right">
                        <a class="btn btn-default" href="@Url.Action("SortDesc", "Home")"><i class="glyphicon glyphicon-arrow-down"></i> Sort Desc</a>
                        <a class="btn btn-default" href="@Url.Action("SortAsc", "Home")"><i class="glyphicon glyphicon-arrow-down"></i> Sort Asc</a>
                    </div>
                </form>
                <p>
                    @if (Model != null)
                    {
                        foreach (int number in Model.Numbers)
                        {
                            <span class="label label-info">@number</span>
                        }
                    }   
                </p>
            </div>
        </div>
    </div>
</div>

首页控制器:

public ActionResult Index()
{
    return View();
}

[HttpPost]
public ActionResult SortDesc([Bind(Include = "Number1, Number2, Number3, Number4")] NumberSetList model)
{

    if (!ModelState.IsValid)
    {
        return View();
    }
    else
    {
        NumberSetList list = new NumberSetList();
        List<int> numbers = new List<int>();
        numbers.Add(model.Number1);
        numbers.Add(model.Number2);
        numbers.Add(model.Number3);
        numbers.Add(model.Number4);
        numbers.OrderByDescending(i => i);
        list.SortOrder = "Desc";
        return View(list);
    }

}

在这个动作中,变量 numbers 没有被赋值。视图如何知道它的存在?你需要设置 list.numbers = numbers; - Nkosi
这会抛出一个错误:严重性代码描述项目文件行抑制状态 错误 CS0029 无法隐式转换类型 'System.Collections.Generic.List<int>' 到 'System.Collections.Generic.List<CSIMediaASPTest.Models.NumberList>' CSIMediaASPTest - Web Develop Wolf
我的错,刚才忘了 List<int> - Nkosi
你在那个操作中实际上想要做什么? - Nkosi
所以我将NumberSetModel中的列表更改为List<int> - 现在看起来不需要额外的类 - 所以现在numbers为空,因为它没有获取输入值 - 我想获取输入值,对其进行排序,将其添加到模型中,然后以正确的顺序显示模型。 - Web Develop Wolf
2个回答

2

试试这个

public class NumberSetList {
    public int NumberSetListId { get; set; }
    public List<NumberSetItem> Numbers { get; set; }
    public string SortOrder { get; set; }
}

public class NumberSetItem {
    public int Value { get; set; }
}

使用for循环创建数字输入。

 @using (Html.BeginForm()) {
    <div class="col-md-9">
        <div class="form-group">
            @if (Model != null && Model.Numbers != null) {
                @for (int i = 0; i < Model.Numbers.Count; i++) {
                    <div class="form-group">
                        @Html.LabelFor(m => m.Numbers[i].Value, "Number " + (i+1).ToString())
                        @Html.TextBoxFor(m => m.Numbers[i].Value, new { @class = "form-control" })
                    </div>
                }
               <div class="col-md-3 text-right">
                   <input id="SortOrder" value="Desc" type="button" class="btn btn-default"><i class="glyphicon glyphicon-arrow-down"></i> Sort Desc</input>
                   <input id="SortOrder" value="Asc" type="button" class="btn btn-default"><i class="glyphicon glyphicon-arrow-down"></i> Sort Asc</input>
               </div>
            }
        </div>
    </div>
}

在视图中

[HttpPost]
public ActionResult Index(NumberSetList model) {
    if (!ModelState.IsValid) {
        return View();
    } else {
        var numbers = model.SortOrder == "Desc" ?
            model.Numbers.OrderByDescending(n => n.Value) : 
            model.Numbers.OrderBy(n => n.Value);
        model.Numbers = numbers.ToList();
        return View(model);
    }
}

生成错误:表达式树可能不包含动态操作 - 这是在 'm.Numbers[i]' 上。 - Web Develop Wolf
那是因为这些链接正在执行GET而不是POST,它们无法执行后者。更新表单以指向动作“@using(Html.BeginForm())”,并将排序作为模型的属性而非两个独立的动作包括进来。 - Nkosi
@WebDevelopWolf,请查看最新更新。请注意,操作名称也已更改。 - Nkosi
请重新检查 Razor 代码,并确保您按照最新更新的方式进行了操作。 - Nkosi
已排序 - 我有两个表单标签 - 感谢所有的帮助。 - Web Develop Wolf
显示剩余3条评论

1
您可以使用多种技术来解决此问题。
将视图名称传递到View方法中,如下所示:
return View("Index", list);
View 方法有许多重载,您可以在此处查看所有重载。熟悉针对您当前情况的重载是很好的选择。

如果您的视图不在与操作相同的文件夹中,则需要传递视图的路径而不仅仅是名称。

另一种方法是只使用一个操作,您也可以将其命名为 Index,但这个操作将采用模型作为参数。您的模型可以具有数字和枚举值(按顺序排列:降序、升序)。在操作方法中,您可以分析模型并执行所需操作。

我更喜欢使用模型的方式。

编辑

我刚刚注意到您的视图中有这行代码:

<a class="btn btn-default" href="@Url.Action("SortDesc", "Home")"><i class="glyphicon glyphicon-arrow-down"></i> Sort Desc</a>

这将触发HTTP GET,因此不会命中您的SortDsc操作方法。从您的操作方法中删除POST或使用一个POST技术(表单)来使用POST命中您的操作方法。

编辑2

说实话,你正在做的事情比你想象的简单得多。首先,当你使用Url.Action时,你没有向你的操作方法传递任何东西,那么它怎么知道数字呢?我通常会使用AJAX调用我的操作方法并获取结果并显示结果。

没有AJAX,您需要为升序和降序使用一个表单。或者您可以使用单选按钮让用户首先选择顺序。

这里是一些使用单选按钮完成它的代码。

操作:

[HttpPost]
public ActionResult SortDesc([Bind( Include = "Number1, Number2, Number3, Number4, SortOrder" )] NumberList model) {

   if( !ModelState.IsValid ) {
      return View("Index");
   }
   model.Numbers = new List<int>();
   model.Numbers.Add( model.Number1 );
   model.Numbers.Add( model.Number2 );
   model.Numbers.Add( model.Number3 );
   model.Numbers.Add( model.Number4 );
   model.Numbers.Add( model.Number5 );
   if (model.SortOrder == "Desc" ) {
      model.Numbers = model.Numbers.OrderByDescending( i => i ).ToList();
   }
   else {
      model.Numbers = model.Numbers.OrderBy( i => i ).ToList();
   }

   return View("Index", model);

}

模型:

public class NumberList {
   public int Number1 { get; set; }
   public int Number2 { get; set; }
   public int Number3 { get; set; }
   public int Number4 { get; set; }
   public int Number5 { get; set; }
   public int NumberListId { get; set; }
   public List<int> Numbers { get; set; }
   public string SortOrder { get; set; }
}

视图:

@using( Html.BeginForm( "SortDesc", "Home", FormMethod.Post ) ) {
<div class="row">
    <div class="col-md-12">
        <div class="panel panel-info">
            <div class="panel-heading"><i class="glyphicon glyphicon-arrow-right"></i> Enter Your Four Numbers</div>
            <div class="panel-body">
                <form class="form-inline">
                    <div class="col-md-9">
                        <div class="form-group">
                            <label class="sr-only" for="number1">1st Number</label>
                            <input type="number" class="form-control" id="number1" name="Number1" placeholder="#1">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number2">2nd Number</label>
                            <input type="number" class="form-control" id="number2" name="Number2" placeholder="#2">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number3">3rd Number</label>
                            <input type="number" class="form-control" id="number3" name="Number3" placeholder="#3">
                        </div>
                        <div class="form-group">
                            <label class="sr-only" for="number4">4th Number</label>
                            <input type="number" class="form-control" id="number4" name="Number4" placeholder="#4">
                        </div>
                        <div class="form-group">
                            <input type="radio" class="form-control" id="number4" name="SortOrder" value="Desc">
                        </div>
                        <div class="form-group">
                            <input type="radio" class="form-control" id="number4" name="SortOrder" value="Asc">
                        </div>
                    </div>

                    <div class="col-md-3 text-right">
                        <button class="btn btn-default"><i class="glyphicon glyphicon-arrow-down"></i> Sort </button>
                        @*<a class="btn btn-default"><i class="glyphicon glyphicon-arrow-down"></i> Sort Asc</a>*@
                    </div>
                </form>
                <p>
                    @if( Model != null ) {
                        foreach( int number in Model.Numbers ) {
                        <span class="label label-info">@number</span>
                        }
                    }
                </p>

            </div>
        </div>
    </div>
</div>

}

你需要将数字传递到动作中。你还需要帮忙吗? - CodingYoshi
动作方法SortDesc具有属性 [HttpPost],因此请确保您没有使用 GET 调用它。换句话说,仅在浏览器中打开 /Home/SortDesc 是不可能的,它必须是来自某个其他页面(例如 /Home/Index)的 POST 调用。 - Peter B
我之前认为这就是 [Bind(Include = "Number1, Number2, Number3, Number4")] 的作用? - Web Develop Wolf
那个触发动作很好,但仍然没有传入四个输入框中的数字? - Web Develop Wolf
好的,我明白你想做什么。请看我的第二次编辑。但是,请使用 AJAX 处理这种情况。这样可以得到你想要的结果。复制我所有的内容并尝试一下。 - CodingYoshi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接