【问题标题】:Javascript Windows.Location pass complex JSON objectJavascript Windows.Location 传递复杂的 JSON 对象
【发布时间】:2017-07-10 22:16:55
【问题描述】:

我将以下对象传递给 MVC 控制器:

this.JsonData = {
    "__RequestVerificationToken": $('input[name=__RequestVerificationToken]').val(),
    "searchMode": {
        "mode": Number(mode.val()),
        "pageSize": Number(pagesize.val()) || 5,                                       "pageNumber": Number(pagenumber.val()) || 1,                
        "sortField": sortfield.val() || "Ref",
        "sortDirection": sortdirection.val() || "desc"
    },
    "searchData": {
        "Compare": Number(StdComparison.val()),
        "SearchTextFrom": searchText.val(),
        "SearchTextTo": searchTextTo.val()
    }

这没问题,但我最近提出了一个要求,我希望对此对象进行编码,以便与 javascript 函数 Window.location 一起使用

我使用过的建议:

how-to-pass-complex-json-object-in-url-using-javascript

window.location + "?SearchCriteria=" + JSON.Stringify(this.JsonData);

创建以下请求:

Controller/Action?SearchCriteria={
    "__RequestVerificationToken": "tokenvalue",
    "searchMode": {
        "mode": 2,
        "pageSize": 5,
        "pageNumber": 1,
        "sortField": "Ref",
        "sortDirection": "desc"
    },
    "searchData": {
        "Compare": 1,
        "SearchTextFrom": "From A",
        "SearchTextTo": "To Z"
    }
}

window.location + "?SearchCriteria=" + this.JsonData;

产生了以下内容:

Controller/Action?SearchCriteria=[object%20Object]

上面两个都没有找到页面错误。

更新:

我在寻求答案的过程中向前迈进了一步。

好的,根据帮助者的要求,我已经包含了更多的源代码。

我有三门课。

public class MainSearch
{
    public MainSearch()
    {
        SearchData searchData = new SearchData();
        SearchMode searchMode = new SearchMode();
    }
    public SearchData searchData { get; set; }
    public SearchMode searchMode { get; set; }
    public int? page { get; set; }
    public object ToPagedListParameters(int pagenumber)
    {
        searchMode.pageNumber = pagenumber;
        return page;
    }
    public IList<string> ValidationErrorMessages { get; set; }
}
public class SearchData
{
    // Fields used for the ticket number search
    public int? ticketNumberCompare { get; set; }
    public string ticketSearchTextFrom { get; set; }
    public string ticketSearchTextTo { get; set; }

}
public class SearchMode
{
    public int? mode { get; set; }
    public int? pageNumber { get; set; }
    public int? pageSize { get; set; }
    public string sortDirection { get; set; }
    public string sortField { get; set; }
    public string userURN { get; set; }
    public string __RequestVerificationToken { get; set; }
}

这些类包含用于搜索的条件(SearchData 已被截断)

以下是我的控制器代码:

[HttpGet]
public ActionResult DownloadFileCSV(MainSearch search)
{
    string fileName = Server.MapPath("~/Content/Pdf/") + "somefile.pdf";
    byte[] fileContents = System.IO.File.ReadAllBytes(fileName);
    return File(fileContents, "application/pdf", "result.pdf");
}

最后,从 cshtml 文件进行的 Ajax 调用。

$("#DownloadAttachmentCSV").click(function () {
    $.ajax(
        {
            url: '@Url.Action("DownloadFileCSV", "Home")',
            contentType: 'application/json; charset=utf-8',
            datatype: 'json',
            data: JsonData,  
            type: "GET",
            success: function () {
                window.location = '@Url.Action("DownloadFileCSV", "Home")' + '?' + JsonData;                      
            },
            error: function (xhr, ajaxOptions, thrownError) {
                alert(xhr.status);
                alert(thrownError);
            }
        });
    });

奇怪的是,上面的代码确实有效并且文件已下载,但问题就在这里。 JSON 数据未填充 MainSearch 变量。

到目前为止,我可以获得 JSON 数据以填充 c# 类的唯一方法是将方法更改为 POST。

一定是这样吗?

【问题讨论】:

  • 您可以将复杂的 javascript 对象传递给 GET 方法。您调用的方法的签名是什么?
  • 它在 MVC 控制器操作上使用 HttpGet
  • 是的,我知道 - 方法的签名又是什么(如果它是模型,则显示该模型)
  • 签名为:public FileResult MethodName(SearchCriteria data)
  • 模型为:public class SearchCriteria { public SearchMode searchMode {get;set;} public SearchData searchData {get;set;}}

标签: javascript c# jquery json asp.net-mvc


【解决方案1】:

您不能将复杂的 javascript 对象传递给这样的 GET 方法。 GET 没有正文并且要绑定到模型,您的查询字符串名称/值对必须与您绑定到的对象的属性相匹配。例如要绑定到MainSearchSearchMode 属性的mode 属性,您的查询字符串需要包含

....&SearchMode.mode=2....

将您用于生成 javascript 对象的代码更改为

var data = {
    'searchMode.mode': mode.val(),
    'searchMode.pageSize': pagesize.val() || 5,
    'searchMode.pageNumber': pagenumber.val() || 1,
    'searchMode.sortField': sortfield.val() || "Ref",
    'searchMode.sortDirection':  sortdirection.val() || "desc",
    'searchData.SearchTextFrom': StdComparison.val(),
    'searchData.Compare': searchText.val(),
    'searchData.SearchTextTo': searchTextTo.val(),
}

和 ajax 代码

 $.ajax(
    {
        url: '@Url.Action("DownloadFileCSV", "Home")' + '?' + $.param(data),
        type: "GET",
        success: function () {

还要注意以下几点

  1. 使用Number(..) 将值转换为 number - 全部作为文本通过网络发送
  2. GET 没有正文,因此设置 ajax contentType 选项是 毫无意义
  3. 你的方法没有返回 json 所以datatype: 'json' 不会 感觉。
  4. 不需要将防伪令牌传递给 GET 方法

话虽如此,但不清楚您想在这里做什么。 MainSearch search() 方法中的代码从不使用模型的任何值。它返回一个FileResult,它不能与ajax调用一起使用(但它可以与window.location一起使用,在这种情况下,成功回调中的代码需要是

var baseUrl = '@Url.Action("DownloadFileCSV", "Home")';
var queryString = $.param(data);
window.location = baseUrl + '?' + queryString;

但是不清楚为什么你对方法进行 2 次调用 - ajax 调用,然后是重定向(ajax 调用根本不做任何事情)。

【讨论】:

    【解决方案2】:

    您用作查询参数的任何内容都应经过正确的 URI 编码,尤其是 JSON 之类的内容:

    window.location + "?SearchCriteria=" + encodeURIComponent(JSON.stringify(this.JsonData));
    

    我不确定模型绑定器是否旨在将 GET 请求中的 JSON 转换为类实例,但您在上面所做的尝试绝对不是可行的方法。

    【讨论】:

    • Stringify 我必须把它写成小写,像这样:'&amp;json=' + encodeURIComponent(JSON.stringify(data));
    • @Oscar 谢谢。看来我打错了。
    猜你喜欢
    • 1970-01-01
    • 2020-10-09
    • 2011-01-31
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多