【问题标题】:MVC Partial Views issueMVC 部分视图问题
【发布时间】:2016-05-11 19:19:19
【问题描述】:

我对 MVC 很陌生,我正在尝试找出是否有更好的方法来做到这一点。我有一个文本框供用户输入搜索,然后基于该搜索,我在所述搜索框下方显示一些结果。我试图避免在我的视图中有这么多的代码逻辑,并想知道是否有更好的方法来处理这个问题。这是我现有的代码,根据“Model.Results”的值,如果我的其余逻辑通过,它将返回 3 个部分视图之一或一个按钮:

@section CustomerPrefixInfo
{
    @if (Model.Results == PrefixSearch.SearchResults.CustomerFound)
    {
        @Html.Partial("_CustomerPrefixInfo")
    }
    @if (Model.Results == PrefixSearch.SearchResults.PrefixResultsFound)
    {
        @Html.Partial("_PrefixResults")
    }
    @if (Model.Results == PrefixSearch.SearchResults.AnimalsFound)
    {
        @Html.Partial("_AnimalSearchResults")
    }
    @if (Model.Results == PrefixSearch.SearchResults.ValidNewPrefix)
    {
        using (Html.BeginForm("Index", "PrefixManagement", new { prefix = Model.AnimalPrefix.Prefix, dbPrefix = Model.AnimalPrefix.DbPrefix }))
        {
            <fieldset>
                <input id="btnReservePrefix" type="submit" value="Reserve Prefix" />
            </fieldset>
        }
    }
}

我想把它放在一个控制器中,让它只返回要显示的视图,然后在页面上显示该视图。在做了一些研究之后,我认为使用 Ajax.BeginForm 并将 InsertionMode 设置为 InsertAfter 就可以了:

@using (Ajax.BeginForm("GenericSearch", "Home", FormMethod.Post, new AjaxOptions { InsertionMode = InsertionMode.InsertAfter, UpdateTargetId = "searchResults" }))
{
    <fieldset>
        <input id="btnPrefixSearch" type="submit" value="Prefix Search/Validate"/>
        @Html.EditorFor(model => model.Input)
    </fieldset>
    <div id="searchResults">

    </div>
}

然后我的 GenericSearch Action 使用一个开关来决定返回哪个局部视图:

public ActionResult GenericSearch(PrefixSearch prefixSearch)
{
    //some database logic here to get the results
    switch (prefixSearch.Results)
    {
        case PrefixSearch.SearchResults.CustomerFound:
            return PartialView("_CustomerPrefixInfo", prefixSearch);
        case PrefixSearch.SearchResults.PrefixResultsFound:
            return PartialView("_PrefixResults", prefixSearch);
        case PrefixSearch.SearchResults.AnimalsFound:
            return PartialView("_AnimalSearchResults", prefixSearch);
        default:
            return null;
     }
}

但是当我尝试这样做时,它会将部分视图放在新页面上。

这是我的部分观点之一(它们都是 3 大部分与此相同)

@model MVC_Test_Project.Models.PrefixSearch

@{
    ViewBag.Title = "PrefixResults";
 }

@{
    Layout = null;
 }
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.PrefixResults[0].Prefix)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.PrefixResults[0].CustomerCount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.PrefixResults[0].Link)
        </th>
    </tr>

@foreach (var item in Model.PrefixResults)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Prefix)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CustomerCount)
        </td>
        <td>
            <a href="@item.Link">edit</a>               
        </td>
    </tr>
}
 </table>

任何帮助将不胜感激!

编辑只是一个有用的提示,以防万一有人犯我犯的同样愚蠢的错误,确保你的包在你的脚本之前被调用。

@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/bootstrap")
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.min.js"></script>

当提到使用它们时,我在最后两行中添加了它们,但它们在我的捆绑包之上......因此,ajax 无法正常工作。感谢大家的帮助,现在一切都好! --约瑟夫

【问题讨论】:

  • 你能显示你的部分视图代码吗,它应该在顶部有@{ Layout=null;} 用来告诉它,不要使用任何母版页
  • 我刚刚添加了@{ Layout=null; } 到我的部分观点,它似乎并没有改变结果。我更新了我的帖子以显示我的观点之一。
  • 您是否只想在页面上的一个表格中返回结果?您返回的部分视图是否只是附加到当前结果?如果是这种情况,您需要InsertionMode.Replace,它只是重新渲染searchResults div
  • 确保您在控制器中的 Action 方法上方具有 [HttpPost] 属性。此外,如果您只是“搜索”结果,而不是实际“发布”任何内容,我会推荐一个 GET 请求(不需要 Action 方法上方的属性),并将 FormMethod 更改为 Get ,或尝试将AjaxOptions 中的HttpMethod 设置为"GET"
  • @jpaugh78 为什么要使用 ajax。它似乎无法解决您的具体问题。这是一项很酷的技术,我会做你经常尝试做的事情,但对于你的特定需求来说,这似乎是矫枉过正。

标签: c# ajax asp.net-mvc asp.net-mvc-4


【解决方案1】:

我想把它放在一个控制器中,让它只返回视图

看起来很简单:

视图模型:

public class MyModel
{
  public string PageToRender { get; set; }
}

控制器动作

public ActionResult DoLogic()
{
  //var Results = ?? as The ENum

  switch(Results)
  {
    PrefixSearch.SearchResults.CustomerFound:
      model.PageToRender = "_CustomerPrefixInfo";
    // etc etc
  }    

  return View(model);
}

查看:

 @{if (!string.IsNullOrEmpty(model.PageToRender))
   Html.RenderPartial(model.PageToRender);}

虽然我可能会装饰枚举:

public enum SearchResults
{
  [Display(Name="_CustomerPrefixInfo")]
  CustomerFound
}

然后就没有switch语句了,你只是grab the enum value display attribute's name value

【讨论】:

  • 我在your answer with a comment 上解释了我的反对意见。基于your comment,我会假设我对你投反对票的回答似乎是虚伪的。
  • 我已经编辑了我的答案以包括逻辑可以在哪里 - 他已经提到他会将逻辑放在控制器中;所以我认为这是他前进的方向,并且需要知道如何将结果解析为页面上的 div - 如果您有一点冒犯,请见谅
【解决方案2】:

确保在要执行 Ajax 的页面顶部包含 jQuery 和 jquery.unobtrusive-ajax.js(或 jquery.unobtrusive-ajax.min.js)。

像这样:

<script src="~/scripts/jquery-1.x.x.js" />
<script src="~/scripts/jquery.unobtrusive-ajax.js" />

...
The rest of your page down here
...

这允许部分的回发在页面内呈现,而不是每次都重定向你。

如果您没有 jQuery 文件,或者不确定如何包含它们;在这里阅读:http://www.c-sharpcorner.com/UploadFile/4fcb5a/update-a-div-and-partial-view-using-ajax-beginform-on-form-s/ - 它非常有用。

确保在您的 web.config 文件中也启用了 Unobtrusive JS。它们在&lt;appsettings&gt; 节点中看起来像这样:

<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

如果您正在使用验证 - 我怀疑您是否正在搜索;但请留在我身边 - 你可能还想包括 jquery.validate.jsjquery.validate.unobtrusive.js。这可以允许客户端验证(在可能的情况下)使用户体验更加流畅。

注意:还有 其他方式来处理 Ajax 请求;例如在你自己的 JS 脚本中创建它——这个例子是使用一个已经可用且深受喜爱的库最简单的:)

希望这会有所帮助!

编辑
然后,可以仅在 Controller 内部完成要返回 Partial 视图的 switch。您可以从页面视图中删除逻辑。

然后,Ajax 将负责替换您提供给 Ajax.BeginForm 助手的 div ID 的内容。

您可以完全替换搜索表单 - 使用其 ID,或者更好的是 - 在页面中放置一个空的 &lt;div&gt; 容器,准备在以下位置显示结果:

<div id="searchResults"></div>

然后 Ajax 将返回 Partial 视图并将内容放入您的 searchResults div 中。

编辑 2

我在您的Ajax.BeginFormAjaxOptions 对象中注意到您缺少HttpMethod = "POST"

AjaxOptions 应该如下所示:

new AjaxOptions {
            HttpMethod = "POST",
            UpdateTargetId = "searchResults",
            InsertionMode = InsertionMode.Replace
}

【讨论】:

  • 这并没有回答关于如何切换逻辑的问题。不管 html 怎么渲染,他仍然希望视图中的逻辑。
  • 如果你没看错,他已经把逻辑放在了 Action 的代码中,并决定了返回哪个局部视图......
  • 我已经编辑了我的答案,以阐明逻辑可以在哪里以及如何通过返回部分视图在页面上显示它
  • 很高兴听到您正在取得进展 :) 我总是在 AjaxOptions 对象属性中使用您没有的一件事;那是HttpMethod = "POST" 。尝试添加此内容并告诉我您的进展情况 - 不要将其与现有的 FormMethod.Post 混淆;你可以把它留在...
  • 不可能!容易犯错误。任何人,为了清楚起见,我已经在我的答案编辑中扩展了我的最后评论。祝你好运! :)
猜你喜欢
  • 1970-01-01
  • 2016-03-27
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多