简体   繁体   中英

How to pass 2 variables from jquery AJAX to ASP.Net WebApi2 method?

I can write a JQuery AJAX call to a webapi2 (asp.net) controller with only 1 parameter just fine (one json object), but when attempting to send 2 parameters (a string and an integer) to a call with all else remaining the same, I get

No HTTP resource was found that matches the request URI

error in the browser console. I believe I've tried every combination I can think of to get 2 parameters to pass, but always end up with the same error message: I'm not sure of the correct format for the data, in javascript - I thought I made a JSON object. but did not, I've quoted, unquoted, and tried every combination I can think of. but no joy. Does ASP?Net WebAPI2 not accept more than 1 parameter, (I'm converting ASMX from an old site to api controllers and am stuck on 1 particular one that takes 2 parameters - works fine for ASMX. but webapi doesn't seem to recognize the signature).

web method in C# (i've tried the post, put and delete verbs - no joy)

    [Route("api/DeleteUserSearch")]
    [HttpPost]
    [Authorize(Roles = "admin,paid,vendor,visitor")]
    public async Task<IHttpActionResult> DeleteUserSearch(string userid, int usersearchidx)
    {
        int retval = 0;
        if (IsValidUserId(userid))
        {
            retval = (await userSearch_Data.DeleteSavedSearchAsync(userid, usersearchidx)).xToInt();
        }
        return Ok(retval);
    }

The AJAX call: (one version that worked with ASMX)

function deleteUserSearch(uid, sid) {
$.ajax({
    url: '../../api/DeleteUserSearch',
    dataType: 'json',
    method: 'post',
    data: { userid:  uid , usersearchidx : sid },
    success: function (data) {
        //refresh searches dropdown
        ShowSuccessMsg('Your search has been deleted.');
        $('#SSPopup').modal('hide');
        RetrieveSearchesDD(uid, "#ddlSavedSearches", false, "")
    },
    error: function (err) {
        console.log('Error (deleteUserSearch): ' + JSON.stringify(err, null, 2));
    }
});
};

This works for all other calls with 1 parameter (any object), but does not for more than one. What am I doing wrong here?

Full Error in the Console: (it's obviously a signature problem - the URI is correct).

Error (deleteUserSearch): {
  "readyState": 4,
  "responseText": "{\"Message\":\"No HTTP resource was found that matches the request URI 'https://localhost:44371/api/DeleteUserSearch'.\",\"MessageDetail\":\"No action was found on the controller 'SavedSearches' that matches the request.\"}",
  "responseJSON": {
    "Message": "No HTTP resource was found that matches the request URI 'https://localhost:44371/api/DeleteUserSearch'.",
    "MessageDetail": "No action was found on the controller 'SavedSearches' that matches the request."
  },
  "status": 404,
  "statusText": "error"
}

Solution1

Get data as one object and one parameter from form

When you are passing data as an object like { userid: uid, usersearchidx: sid } you need some changes in your Controller and Action

public class Parameter { public int UserId { get; set; } public int UserSearchIdX { get; set; } } public async Task<IHttpActionResult> DeleteUserSearch([FromForm] Parameter param) { // Your code }

Solution2

Get data as two parameters separately

If you can't change the old code too much and you want to get two parameters separately, then you can do it like this: There is no change in your API:

function deleteUserSearch(uid, sid) {
  $.ajax({
    url: '../../api/DeleteUserSearch?userId=' + uid + '&userSearchIdX=' + sid,
    dataType: 'json',
    method: 'post',
    //data: { userid: uid, usersearchidx: sid },
    success: function (data) {
        alert("Success");
    },
    error: function (err) {
        console.log('Error');
    }
  });
}

And you can send your parameters like a query string:

 function deleteUserSearch(uid, sid) { $.ajax({ url: '../../api/DeleteUserSearch?userId=' + uid + '&userSearchIdX=' + sid, dataType: 'json', method: 'post', //data: { userid: uid, usersearchidx: sid }, success: function (data) { alert("Success"); }, error: function (err) { console.log('Error'); } }); }

OK. Got it figured out. WebApi can only handle one parameter, but it can be anything (an object). Because this is DotNetFW 4.72, the [Form] decorator won't work (DotNetCore only), so I figured I'd just create a JSON object in Javascript and match it with an object in C#.

(I have a class/model called UserSearch with the properties UserId and UserSearch_Idx)

So the working version code is as follows:

    [Route("api/DeleteUserSearch")]
    [HttpDelete]
    [Authorize(Roles = "admin,paid,vendor,visitor")]
    public async Task<IHttpActionResult> DeleteUserSearch(UserSearch p)
    {
        int retval = 0;
        if (IsValidUserId(p.UserId))
        {
            retval = (await userSearch_Data.DeleteSavedSearchAsync(p.UserId, p.UserSearch_Idx)).xToInt();
        }
        return Ok(retval);
    }

On the client side, it's straightforward: Just create a JSON object and assign it's properties. Code on that end looks like so:

function deleteUserSearch(uid, sid) {
    var uSearch = {};
    uSearch.UserId = uid;
    uSearch.UserSearch_Idx = sid;

    $.ajax({
        url: '../../api/DeleteUserSearch',
        dataType: 'json',
        method: 'delete',
        data: uSearch,
        success: function (data) {
            //refresh searches dropdown
            ShowSuccessMsg('Your search has been deleted.');
            $('#SSPopup').modal('hide');
            RetrieveSearchesDD(uid, "#ddlSavedSearches", false, "")
        },
        error: function (err) {
            console.log('Error (deleteUserSearch): ' + JSON.stringify(err, null, 2));
        }
    });
};

Thank you Saeid for the tip (Core has a built in object representing the form data - which is nice)!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM