使用相对URL的Ajax Jquery帖子

时间:2013-03-15 10:03:46

标签: jquery post antiforgerytoken

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

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

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

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

我从来没有在昨天之前使用过Firebug,所以如果有人知道怎么做,可能会有更多的东西可以检查。 (我对MVC和Web应用程序一般都是新手。)

我的控制器方法也有一个突破。仅从创建视图调用时会受到影响。

在绝望中我尝试将呼叫类型更改为GET而不是POST。这导致了一个名为不同名称的控制器方法(HttpGet EDIT),至少可以说是令人不安的。

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

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

更新: Firebug控制台指示正在调用不同的操作。在Create case中它是... / _ an_alphanumeric_literal_ / Order / PopulateAvtalDDL,这就是我想要的。在编辑案例中,它是... / _ an_alphanumeric_literal_ / Order / 编辑 / PopulateAvtalDDL。这是路由问题吗?如果是这样,我仍然没有得到它。两个调用都是从同一个脚本调用的,我只设置了一个路由(基本上是MVC 4的默认路由):

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

更新: 我终于找到了一些相关的信息:Relative URLs in AJAX requests。 那是一个路由问题。如果我将脚本网址从相对PopulateAvtalDDL更改为绝对/_an_alphanumeric_literal_/Order/PopulateAvtalDDL,则可以从两个视图中进行操作。引用链接中的答案表明路径相对于浏览器中的当前URL。在我的情况下是http://localhost:51852/_an_alphanumeric_literal_/Order/Edit/6?markedOrderId=0http://localhost:51852/_an_alphanumeric_literal_/Order/Create?markedOrderId=0。构建相对URL时,将替换最后一个段。在创建案例中创建,但在编辑案例中,它是 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)

1 个答案:

答案 0 :(得分:1)

我终于找到了一些相关信息:AJAX请求中的相对URL。这是一个路由问题。如果我将脚本URL从相对PopulateAvtalDDL更改为绝对/ _an_alphanumeric_literal_ / Order / PopulateAvtalDDL,则它可以从两个视图中进行操作。引用链接中的答案表明路径相对于浏览器中的当前URL。在我的情况下是 http://localhost:51852/_an_alphanumeric_literal_/Order/Edit/6?markedOrderId=0

http://localhost:51852/_an_alphanumeric_literal_/Order/Create?markedOrderId=0。构建相对URL时,将替换最后一个段。在Create创建案例中,但在Edit案例中,它是6(编辑数据的ID)。

我的解决方案:

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