在Ajax请求期间从查询字符串的URL中删除“X-Requested-With”

5
我遇到的问题是由于它属于查询字符串,所以 &X-Requested-With=XMLHttpRequest&_=1462736803425 一直被添加到我的URL中。有没有办法阻止它成为查询字符串,并使用 Ajax.BeginForm 而不进行“hack”操作?
@using (Ajax.BeginForm("Search", "Filter", new { Area = "Music" }, new AjaxOptions { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "body-wrapper", OnSuccess = "updateHistory" }, new { @id = "search-form" }))
{
       <div>
           <i class="fa fa-search"></i>
           <input type="search" placeholder="Search" id="search" name="searchString" />
       </div>
}

public ActionResult Search(string searchString)
{
    //do stuff
    return PartialView();
}

在局部视图页面中,我会获取路径和查询信息:
@Html.HiddenFor(x => Request.Url.PathAndQuery)

Request.Url.PathAndQuery 的值为:http://localhost:1526/Music/Search?searchString=maid&X-Requested-With=XMLHttpRequest&_=1462736803425

然后使用 History.js 更新 URL:

function pushState(target) {
    manualStateChange = false;
    History.pushState(null, null, $("#Request_Url_PathAndQuery").val());
}

enter image description here

3个回答

4

如果不修改"jquery-ajax-unobtrusive.js"源文件,这并不容易。问题出在第117行:

options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });

它在发送请求之前添加了这些数据。在我看来,这有点令人反感,特别是因为该值应该是HTTP头部而不是数据的一部分。

也许可以通过在表单的ajax请求中添加一个beforeSend选项来删除它。你需要定义一个函数:

function removeExtraData(jqXHR, settings) {
  if (settings.data.hasOwnProperty('X-Requested-With')) {
    delete settings.data['X-Requested-With']; // or settings.data['X-Requested-With'] = undefined;
  }
}

您可以通过在表单中添加一个data-ajax-begin HTML属性,其值为removeExtraData,然后使用它。我没有验证过这一点,而且我已经几年没有使用WebForms了,所以我没有设置来测试。
URL的_=1462736803425部分是由jQuery自动添加的,因为请求被设置为不缓存。显然,您可以通过向表单添加一个名称为data-ajax-cache,值为true的HTML属性来摆脱它。当然,这可能会缓存您的请求,这可能不是您想要的。

谢谢回答,这解决了一些问题。但是 settings 没有 data 属性,我也找不到要删除的头文件。 - Martin Dawson
我能想到的另一种方法是不使用Ajax.BeginForm。使用Html.BeginForm并直接使用jQuery提交表单以进行ajax。但这需要相当多的工作。 - Heretic Monkey
感谢您的帮助。使用ajax helpers时出现这种问题真的很烦人。如果没有更好的答案,我稍后会给您提供奖励。 - Martin Dawson

0

我认为你可以通过覆盖URL路径来解决这个问题。

在Application_BeginRequest()中,您可以检查任何需要的条件,并使用context.RewritePath()删除不必要的参数。

类似于以下内容:

    protected override void Application_BeginRequest(object sender, EventArgs e)
    {
        base.Application_BeginRequest(sender, e);
        var urlpath = HttpContext.Current.Request.Url.PathAndQuery; //Modify this based on condition
        if(<condition>)
            Context.RewritePath(<updatedpath>);
    }

这可能解决你的问题,但我不能确定这是否是一个好的方法。

这是MVC管道中的一个方法。如果您没有自定义实现,可以直接使用它,因为它还会调用基本函数。 - Krishna Chaithanya Muthyala

0
我所使用的方法是这样的,虽然它是一种hack而且不太理想,如果有更好的方法请告诉我。它会从URL中删除查询字符串参数,因为xhr总是附加在末尾,所以这个方法是可行的。
function pushState(target) {
    //Remove the queryString parameter of xhr that gets appened in 117 of ajax-unobtrusive.js
    var index = target.indexOf("?X-Requested-With");
    if (index === -1) 
        index = target.indexOf("&X-Requested-With");

    target = target.replace(target.substring(index), "");

    manualStateChange = false;
    History.pushState(null, $("input#Title").val(), target);
}

根据Mike的评论进行编辑:

@using (Html.BeginForm("Index", "Search", new { area = "Media" }, FormMethod.Get, new { @id = "search", data_url = Url.Action("SetSearchTags", "Search", new { Area = "Media" }) }))
{
    <i class="fa fa-search"></i>
    <input type="search" placeholder="Search" id="search" name="searchString" />

    <div id="filter" name="filter">
        <span><strong>Syntax</strong></span>

        @foreach (var item in SearchContext.SearchFilters)
        {
            <div id="filter-@item">
                @Html.DisplayFor(x => item)
            </div>
        }
    </div>
}

$("form#search").submit(function (event) {
    event.preventDefault();

    var $form = $(this);
    var searchString = $form.find("input[type='search']").val();
    var url = $form.attr("action");
    var method = $form.attr("method");

    $.ajax({
        url: url,
        data: { searchString: searchString },
        method: method,
        success: function (data) {
            $('#body-content').html(data);
            updateHistory(true);
        }
    });
});

function updateHistory(useQuery) {
    var path = (useQuery === true) ? $("#Request_Url_PathAndQuery").val() : $("#Request_Url_AbsolutePath").val();

    pushState(path);
};

基本上,无论我在哪里需要查询字符串参数,我都只能在jquery中手动完成,而不能使用辅助函数。

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