@Ajax.ActionLink generates URL with route parameter instead of POST body, throws jQuery exception on click

时间:2017-10-12 09:44:17

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

I'm trying to render a series of buttons in a ASP.NET MVC 5 View.

Each button should invoke an HTTP POST action in the controller, passing a reportId parameter as part of the POST body. The reportId is a GUID in the typical {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} format.

Here is the view content which renders the buttons:

@foreach (Subscription sub in Model)
{
    <tr>
        <td>
            @Ajax.ActionLink(
                sub.Description,
                "SendReport",
                new {reportId = sub.SubscriptionID},
                new AjaxOptions
                {
                    Confirm = $"Email {sub.Description} report?",
                    HttpMethod = "POST",
                    LoadingElementId = "sending-" + sub.SubscriptionID,
                    UpdateTargetId = "submitstatus-" + sub.SubscriptionID
                },
                new { @class = "btn btn-default"})
            <span id="sending-@sub.SubscriptionID" style="display: none">Sending...</span>
            <span id="submitstatus-@sub.SubscriptionID"></span>
        </td>
    </tr>
}

It shouldn't be necessary to specify that the AjaxOptions.HttpMethod = "POST" because the MSDN documentation says that POST is the default, but I've included that for clarity.

I have installed the Microsoft.jQuery.Unobtrusive-Ajax package version 3.2.3. I've added a bundle to the App_Start\BundleConfig.cs for the additional scripts:

        bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include(
                    "~/Scripts/jquery.unobtrusive-ajax*"));

And I've added the script bundle to the default _Layout.cshtml:

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/jqueryajax")
    @RenderSection("scripts", required: false)
  </body>
</html>

And I've checked that the web.config enables unobtrusive AJAX:

<appSettings>
  <add key="webpages:Version" value="3.0.0.0" />
  <add key="webpages:Enabled" value="false" />
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

When I view the page in Internet Explorer 11, the buttons render nicely as buttons, and they do display the confirmation dialog when clicked. I believe this is functionality that the AJAX script provides, which indicates that the script is loaded correctly.

But the button action URL includes the reportId, eg /Home/SendReport?reportId=%7B86D7B9E1-1D13-4EE8-8059-7F03C17520CD%7D. I was expecting the reportId to be submitted as POST body content. I was expecting that the action URL would just be the controller action e.g /Home/SendReport, without the reportId parameter.

Question 1: Why is the reportId in the button URL and not just the POST body?

Question 2: When the button is clicked, an exception is thrown inside jQuery-3.2.1.js.

Unhandled exception at line 1580, column 2 in 
http://localhost:64690/Scripts/jquery-3.2.1.js

0x800a139e - JavaScript runtime error: Syntax error, unrecognized expression: #sending-{55E625A8-1754-42AE-AD11-C1AEF10EB208}

I don't understand what's causing this exception. Is it because of the incorrect URI? Is there something wrong with this id value?

1 个答案:

答案 0 :(得分:0)

根据我收到的评论,我用带有隐藏输入字段的BeginForms替换了ActionLinks来存储相应的reportId。

我还从AJAX使用的HTML元素ID中删除了{和}字符,修复了jQuery异常。我想这些角色会干扰在JavaScript中定位元素。

@foreach (Subscription sub in Model)
{
    <tr>
        <td>
            @using (Ajax.BeginForm(
                "SendReport", 
                new AjaxOptions
                {
                    Confirm = $"Email {sub.Description} report?",
                    LoadingElementId = "sending-" + sub.SubscriptionID.Trim('{', '}'),
                    UpdateTargetId = "submitstatus-" + sub.SubscriptionID.Trim('{', '}')
                }))
            {
                <input type="hidden" name="reportId" value="@sub.SubscriptionID"/>
                <input type="submit" value="@sub.Description"/>
            }
        </td>
        <td>
            <span id="sending-@sub.SubscriptionID.Trim('{', '}')" style="display: none">Sending...</span>
            <span id="submitstatus-@sub.SubscriptionID.Trim('{', '}')"></span>
        </td>
    </tr>
}