1

I cannot figure out how to get the following code working in my little demo ASP.NET application, and am hoping someone here can help.

Here is the javascript:

function checkUserName() {
    var request = createRequest();
    if (request == null) {
        alert("Unable to create request.");
    } else {
        var theName = document.getElementById("username").value;
        var userName = escape(theName);
        var url = "Default.aspx/CheckName";
        request.onreadystatechange = createStateChangeCallback(request);        
        request.open("GET", url, true);
        request.setRequestHeader("Content-Type", "application/json");
        //none of my attempts to set the 'values' parameter work   
        var values =  //JSON.stringify({userName:"userName"}); //"{userName:'temp name'}"; //JSON.stringify({ "userName":userName });
        request.send(values);
    }
}

Here is the method in my *.aspx.cs class:

[WebMethod]
[ScriptMethod(UseHttpGet=true)]
public static string CheckName(string userName)
{
    string s = "userName";
    return s + " modified backstage";
}

When this code runs I receive this exception:

---------------------------
Message from webpage
---------------------------
{"Message":"Invalid web service call, missing value for parameter: \u0027userName\u0027.","StackTrace":"   at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n   at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n   at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n   at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
---------------------------
OK   
---------------------------

I started searching here, then went on to several threads on SO, trying quite a few combinations of quotation marks and key-value pairs, but nothing I've tried has worked.

When I remove the parameter from the C# method and request.send(), I get a response in my JS callback that I can work with. But as soon as I try to do something with parameters, I get the above exception. I'd like to know how to do this without using jQuery, if possible.

Thanks in advance.

FINAL VERSION Using Alexei's advice, I ended up with the following, which works. The URL was missing the apostrophes on either end of the parameter value; this was keeping the call from going through.

function checkUserName() {
    var request = createRequest();
    if (request == null) {
        alert("Unable to create request.");
    } else {
        var theName = document.getElementById("username").value;
        var userName = encodeURIComponent(theName); 
        var url = "Default.aspx/CheckName?name='" + theName + "'";
        request.onreadystatechange = createStateChangeCallback(request);
        request.open("GET", url, true);
        request.setRequestHeader("Content-Type", "application/json");       
        request.send();
    }
}
RobC
  • 1,303
  • 3
  • 15
  • 32

5 Answers5

3
request.send(values);

This won't work with a "GET". Try

request.open("POST", url, true);

http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp

Alan S
  • 439
  • 3
  • 13
  • I thought adding [ScriptMethod(UseHttpGet=true)] to my server-side method solved this problem. Am I wrong? – RobC Apr 23 '15 at 16:24
  • 1
    The attribute won't affect how the information is sent but just instructs it on where to obtain the parameters. If it's true then you should use "GET" and pass the parameters in the query string. If false then you can use "POST" and specify them in the send function. – Alan S Apr 23 '15 at 16:42
2

Like Alan said, use the POST method. Or pass your arguments in your URL before opening it, e.g.

var url = "Default.aspx/CheckName?userName=" + values;

EDIT : no, it's probably a bad idea since you want to send JSON, forget what I said.

  • 1
    If you figured out your answer was wrong, it's better to delete it. – Ondrej Tucny Apr 23 '15 at 16:10
  • I don't need to send JSON. That was just one of the suggestions I came across in my attempt to figure this out. Pasting the arguments into the URL doesn't work, either.The server-side method doesn't seem to get hit. – RobC Apr 23 '15 at 16:29
2

You need to:

  • decide whether you want GET or POST. For GET request you need all parameters to be in Url (and body to be empty), for POST you can use both. As of current code you are expecting GET, but sending POST.
  • properly add query parameter - name and encoded value. encodeUriComponent is JavaScript function of choice, see Build URL from Form Fields with Javascript or jquery for details
  • if using POST you need to properly encode parameters there too as well specify correct "content-type" header.
  • if sending JSON you need to decode JSON server side.

Alternatively you can use hidden form to perform POST/GET as covered in JavaScript post request like a form submit

Side note: jQuery.ajax does most of that for you and good source to look through if you want to do all yourself.

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Thanks for your suggestions. I attempted to edit my original post with your suggestions--hopefully I didn't misunderstand anything. – RobC Apr 23 '15 at 17:11
  • I got something working and added it to my original question. Thanks for your help. – RobC Apr 23 '15 at 18:11
0

Given that your server side method asks for GET, you need:

request.open("GET", url + "?username=" + userName, true);
request.send();

The works for me:

function checkUserName() {

    var request =  new XMLHttpRequest();

    if (request == null) {
        alert("Unable to create request.");
    } else {        
        var userName = "Shaun Luttin";
        var url = '@Url.RouteUrl(new{ action="CheckName", controller="Home"})';

    request.onreadystatechange = function() {
        if (request.readyState == XMLHttpRequest.DONE ) {
           if(request.status == 200){
               document.getElementById("myDiv").innerHTML = request.responseText;
           }
           else if(request.status == 400) {
              alert('There was an error 400')
           }
           else {
               alert('something else other than 200 was returned')
           }
        }
    }

        request.open("GET", url + "?username=" + userName, true);
        request.send();
    }
}

With this on the server side:

[HttpGet]
public string CheckName(string userName)
{
    return userName + " modified backstage";
}
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • 1
    Thanks for your quick response, but I'm trying to do this without ASP.NET MVC, which this uses, right? – RobC Apr 23 '15 at 16:23
  • @RobC This should work without MVC too. You just need to use `send()` without a value and put your value in the url. – Shaun Luttin Apr 23 '15 at 16:32
  • Side note: This Razor view should not work correctly for most urls as `@` will Html-encode that value leading to almost the same result as OP have. Proper creation of url for JavaScript in MVC is covered in many posts, as well as proper creations of Url in JavaScript (like http://stackoverflow.com/questions/4006991/build-url-from-form-fields-with-javascript-or-jquery) – Alexei Levenkov Apr 23 '15 at 16:38
  • @ShaunLuttin I should have been more precise - exactly that code would work fine as it have all parameters for `Url.Action` hardcoded, as soon as you start using some more data like `...action="CheckName", new {Previous=lastEnteredUserNameWithAmpersand})` one will get in trouble... So in general it is better to always properly write urls for JavaScript... – Alexei Levenkov Apr 23 '15 at 16:49
0

If you need to go for POST, then you need to send it like this.

var values = JSON.stringify({"'userName':'"+ userName+ "'"});

And you have to change HttpGet to HttpPost

Arindam Nayak
  • 7,346
  • 4
  • 32
  • 48