javascriptc#asp.netjsonfetch-api

POST request called to .aspx file returns empty JSON


I'm trying to send a POST request from a .js function to an .aspx file with a JSON body. At the moment I only want it to deserialize the JSON into an Input object and serialize it back into JSON before returning the 'obj' element. My issue is that when I'm trying to print my response in the .js function, it is empty.

The body I'm sending: {"obj":"ASM10007-1A","objType":"part"}

The response I'm expecting: {"obj":"ASM10007-1A"}

Actual output:
enter image description here

I have no idea what to do here, so please help.

.js file

async function JS_PostRequest(obj, objType) {
    var url = T_wroot + 'tweak/HS2-tweak/parts/excelcreator.exe.aspx';

    console.log("URL: " + url);

    const data = {
        obj: obj,
        objType: objType,
    };

    console.log("POST request body: " + JSON.stringify(data));
    
    const options = {   method: 'POST',
                        headers: {'Content-Type': 'application/json'},
                        body: JSON.stringify(data) };
    
    await fetch(url, options)
    .then(function(res) {
        if (res.ok) {
            console.log("response:" + JSON.stringify(res));
            return res;
        }
        if (!res.ok) {
            throw new Error(`HTTP error, status = ${res.status}`);
        }
    })
    .catch((err) => {
        console.error(`Fetch error: ${err}`);
    });
}

.aspx file

<%
    string obj = Request.QueryString["o"];
    string objType = Request.QueryString["t"];
    
    try
    {
        var strJSON = String.Empty;
     
        //Request.InputStream.Position = 0;
        using (var inputStream = new StreamReader(Request.InputStream))
        {
            strJSON = inputStream.ReadToEnd();
        }
     
        var data = Newtonsoft.Json.JsonConvert.DeserializeObject<Input>(strJSON);
        
        string message;
        if (data != null)  // Check if 'data' is not null
        {
            if (data.obj != null)  // Check if 'obj' inside 'data' is not null
            {
                message = data.obj;  // Assign the value of 'data.obj' to 'message'
            }
            else
            {
                message = "No message received";  // Assign default value if 'obj' is null
            }
        }
        else
        {
            message = "No message received";  // Assign default value if 'data' is null
        }
        
        var responseObj = new {
            response = message
        };
        string jsonResponse = Newtonsoft.Json.JsonConvert.SerializeObject(responseObj);
        
        Response.ContentType = "application/json";
        Response.Write(jsonResponse);
        Response.End();
    }
    catch (Exception e)
    {
     
        Response.Write("ASPX error: " + e.Message);
     
    }
%>

<script runat="server>
    public class Input 
    {
        public string obj { get; set; }
        public string objType { get; set; }
    }
</script>

Solution

  • First, that's not the best idea to have a webapi endpoint inside an *.aspx page. Consider exposing a WebAPI endpoint.

    Anyway, two problems.

    First, your server side most probably throws the ThreadAboutException which is what old ASP.NET does when you try to put your hands on Response directly.

    One of the ways to overcome this problem is to add an explicit try-catch that silents down this:

        ...
    
            var responseObj = new {
                response = message
            };
            string jsonResponse = Newtonsoft.Json.JsonConvert.SerializeObject(responseObj);
    
            Response.Clear(); // added!
            Response.ContentType = "application/json";
            Response.Write(jsonResponse);
            Response.End();
        }
        // added!
        catch( System.Threading.ThreadAbortException )
        {
    
        }
        catch (Exception e)
        {
            Response.Write("ASPX error: " + e.Message);
        }
    

    But then, your client code is the real issue. Why you mix async-await with then-catch? Your function is already async but instead of taking advantage of it, you mix both styles.

    And you forgot to read the stream content. A refactored client side to let you get started:

            ....
    
            const options = {   method: 'POST',
                                headers: {'Content-Type': 'application/json'},
                                body: JSON.stringify(data) };
    
            try {
                var response = await fetch(url, options);
                var res = await response.text();
    
                // this correctly shows server response now
                console.log("response:" + res);
            }
            catch (e) {
                console.log(e);
            }