1

我有一个创建视图和一个编辑视图,几乎相同。它们都包含一个级联下拉列表。第二个列表的值是正在创建或编辑的数据的一部分。第一个下拉列表只是第二个列表中值的过滤器。

两个视图都使用相同的脚本,该脚本在第一个下拉列表中附加了更改事件的处理程序。处理程序对控制器中的方法进行发布。

当我运行创建视图并更改第一个下拉列表时,它工作正常。第二个列表已更新。当我在编辑视图中尝试时,我收到 500 内部服务器错误。

我看过Firebug。我在处理程序中放了一个中断。选择时在这两种情况下都会调用它。发送的数据看起来是一样的( $(this).serialize() 看起来一样)。
Firebug 控制台显示:所需的防伪表单字段“__RequestVerificationToken”不存在。我没有看到我需要一个调用此方法,但当然还有其他方法(操作)确实需要一个。

不过,我在昨天之前从未使用过 Firebug,所以如果有人知道如何使用,可能还有很多东西可以检查。(总的来说,我对 MVC 和 Web 应用程序完全陌生。)

我的控制器方法也有中断。仅在从创建视图调用时会被击中。

无奈之下,我尝试将调用类型更改为 GET 而不是 POST。这导致调用了一个具有不同名称的控制器方法(HttpGet EDIT),我觉得至少可以说令人不安。

我感觉找不到我正在调用的方法(在编辑中)。相反,尝试使用其他方法(我不知道是哪一种),并且该方法需要防伪令牌。

编辑: 一阵新鲜空气,我意识到我当然知道调用哪个动作:这是 HttpPost Edit 动作(需要防伪令牌)。这当然是正常的表单提交操作。在调试器中快速运行证实了这一点。这个调用由于手头的原因而失败的事实是清楚的。但是为什么这个动作会被调用呢?

更新: Firebug 控制台指示正在调用不同的操作。在 Create 案例中,它是 .../_an_alphanumeric_literal_/Order/PopulateAvtalDDL,这正是我想要的。在 Edit 情况下,它是 .../_an_alphanumeric_literal_/Order/ Edit /PopulateAvtalDDL。这是路由问题吗?如果是这样,我还是不明白。两个调用都是从同一个脚本发出的,我只设置了一个路由(基本上是 MVC 4 的默认路由):

routes.MapRoute(
            name: "Default",
            url: "_an_alphanumeric_literal_/{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

更新: 我终于找到了一些相关信息:AJAX 请求中的相对 URL。那就是路由问题。如果我将我的脚本 URL 从相对PopulateAvtalDDL更改为绝对/_an_alphanumeric_literal_/Order/PopulateAvtalDDL,则它适用于两个视图。引用链接中的答案表明路径相对于浏览器中的当前 URL。在我的情况下是http://localhost:51852/_an_alphanumeric_literal_/Order/Edit/6?markedOrderId=0and http://localhost:51852/_an_alphanumeric_literal_/Order/Create?markedOrderId=0。当构建相对 URL 时,最后一段被替换。在 Create 案例中是Create,但在 Edit 案例中它是6(已编辑数据的 ID)。我明白发生了什么!

然后我的解决方案:

在过滤器 DDL 周围添加一个 div(在两个视图中)设置 URL: <div id="kundDDL" data-url="@Url.Action("PopulateAvtalDDL", "Order")">。然后在脚本中访问那个 URL url: $('#kundDDL').data('url')

这是创建视图的代码:

@model AssetMgmt.Models.OrderEditVM
@using AssetMgmt.Models;

@{
    ViewBag.Title = MsgString.LblCreateNew + " order";
}

<h2>@ViewBag.Title</h2>


@using (Html.BeginForm(null, null, FormMethod.Post))
{
    @Html.ValidationSummary(true)
    @Html.AntiForgeryToken()

    @Html.HiddenFor(m => m.MarkedOrderId)

    <fieldset>
        <legend>Filter</legend>

        <div class="editor-label">
            @Html.LabelFor(m => m.KundId)
        </div>
        <div class="dropdownlist">
            @Html.DropDownListFor(m => m.KundId, Model.KundDropDown, string.Empty)
        </div>
        <div class="dropdown-validation-error">
            @Html.ValidationMessageFor(model => model.KundId)
        </div>
    </fieldset>

    <fieldset>
        <legend>Orderdata</legend>

        <div id="avtalDDL">
            @Html.Partial("_AvtalDDL")
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Ordernummer)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Ordernummer)
            @Html.ValidationMessageFor(model => model.Ordernummer)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Beställare)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Beställare)
            @Html.ValidationMessageFor(model => model.Beställare)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Orderdatum)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Orderdatum)
            @Html.ValidationMessageFor(model => model.Orderdatum)
        </div>

        <p>
            <input type="submit" value="@MsgString.LblSave" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink(MsgString.LblBack, "Index", new { markedOrderId = Model.MarkedOrderId })
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript" src="~/Scripts/jquery.maskedinput-1.3.1.min.js"></script>
    <script type="text/javascript" src="~/Scripts/assetMgmtMasks.js"></script>
    <script src="~/Scripts/assetMgmtOrderPopulateDDL.js" type="text/javascript"></script>
}

这是编辑视图:

@model AssetMgmt.Models.OrderEditVM
@using AssetMgmt.Models;

@{
    ViewBag.Title = MsgString.LblEdit + " order";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm(null, null, FormMethod.Post))
{
    @Html.ValidationSummary(true)
    @Html.AntiForgeryToken()

    @Html.HiddenFor(model => model.OrderId)
    @Html.HiddenFor(model => model.Timestamp)
    @Html.HiddenFor(model => model.MarkedOrderId)

    <fieldset>
        <legend>Filter</legend>

        <div class="editor-label">
            @Html.LabelFor(m => m.KundId)
        </div>
        <div class="dropdownlist">
            @Html.DropDownListFor(m => m.KundId, Model.KundDropDown, string.Empty)
        </div>
        <div class="dropdown-validation-error">
            @Html.ValidationMessageFor(model => model.KundId)
        </div>
    </fieldset>

    <fieldset>
        <legend>Orderdata</legend>

        <div id="avtalDDL">
            @Html.Partial("_AvtalDDL")
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Ordernummer)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Ordernummer)
            @Html.ValidationMessageFor(model => model.Ordernummer)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Beställare)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Beställare)
            @Html.ValidationMessageFor(model => model.Beställare)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Orderdatum)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Orderdatum)
            @Html.ValidationMessageFor(model => model.Orderdatum)
        </div>

        <p>
            <input type="submit" value="@MsgString.LblSave" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink(MsgString.LblBack, "Index", new { markedOrderId = Model.MarkedOrderId })
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript" src="~/Scripts/jquery.maskedinput-1.3.1.min.js"></script>
    <script type="text/javascript" src="~/Scripts/assetMgmtMasks.js"></script>
    <script src="~/Scripts/assetMgmtOrderPopulateDDL.js" type="text/javascript"></script>
}

剧本:

$(document).ready(function () {
    //Kund select
    $('#KundId').change(function () {
        $.ajax({
            url: 'PopulateAvtalDDL',
            type: 'post',
            data: $(this).serialize(),
            success: function (result) {
                $('#avtalDDL').html(result);
            },
            error: function (xhr, ajaxOptions, thrownError) {
                alert(xhr.status);
                alert(xhr.statusText);
                alert(thrownError);
            }
        });
        return false;
    });
});

控制器方法的签名:

[HttpPost]
public PartialViewResult PopulateAvtalDDL(int kundId = 0)
4

1 回答 1

1

我终于找到了一些相关信息:AJAX 请求中的相对 URL。这是一个路由问题。如果我将我的脚本 URL 从相对 PopulateAvtalDDL 更改为绝对 /_an_alphanumeric_literal_/Order/PopulateAvtalDDL 它适用于两个视图。引用链接中的答案表明路径相对于浏览器中的当前 URL。在我的情况下是
http://localhost:51852/_an_alphanumeric_literal_/Order/Edit/6?markedOrderId=0
and
http://localhost:51852/_an_alphanumeric_literal_/Order/Create?markedOrderId=0。当构建相对 URL 时,最后一段被替换。在 Create 案例中为 Create,但在 Edit 案例中为 6(已编辑数据的 ID)。

然后我的解决方案:

在过滤器 DDL 周围添加一个 div(在两个视图中)设置 URL:
<div id="kundDDL" data-url="@Url.Action("PopulateAvtalDDL", "Order")">
然后在脚本中访问那个 URL
url: $('#kundDDL').data('url')

于 2013-03-18T09:01:50.820 回答