2

I'm working with my project where using Asp.net with c# and Javascript. I have my controller set up with c# where it accepts an object, and two additional variables. It is a HttpPost request, and it works fine until I added the additional variables. I've used console.log in my fetch json function to check that i truly get the desired values, which I am. This fetch works fine with postman!

I've also tried swiching places on the Rented object, so that it is in the last position, if the Body of fetch was sent in last aswell, but it did not work. This is what I get back when calling the function in my chrome browser: https://localhost:44363/rent/save?movieId=2&maxRents=3 Status = 400

Feels like I'm missing something very basic here, maybe you can't send both variables and body at the same time with a request?

Here's the controller code:

[HttpPost("save")]

        public ActionResult<Rented> SaveRent(Rented newLoan, int movieId, int maxRents)
        {

            var amountOfRent = _appDbContext.Rents.Where(m => m.MovieId == movieId);

            if (maxRents <= amountOfRent.Count())
            {
                _appDbContext.Rents.Add(newLoan);
                _appDbContext.SaveChanges();
                return newLoan;
            }
            else
            {
                return BadRequest();
            }
        }

And here's the Fetch function:

function addToStudio(element) {
    var movieId = element.id;
    var studioId = element.value;
    var maxRents = element.name;
    var newId = Number(movieId);
    var newStudioId = Number(studioId);
    console.log(maxRents);
    fetch('https://localhost:44363/rent/save?movieId=' + movieId + '&maxRents=' + maxRents, {
      method: 'POST',
      body: JSON.stringify({
        studioId: newStudioId,
        movieId: newId
      }),
      headers: {
        "Content-type": "application/json; charset=UTF-8"
      }
    })
    .catch(err => console.error("response-error", err)) 
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(err => console.error("json error", err)) 

    container.innerHTML = `<h1>Saved</h1>`
  }

2
  • Hi, welcome to so, your controller method is expecting Rented newLoan, int movieId, int maxRents & your sending an object {studioId: newStudioId,movieId: newId}? also your missing postFromBody Commented Feb 1, 2020 at 8:31
  • @saj I'm sending an object, which is the Rented newLoan, which will need the body to get its information. Then I'm sending 2 int variables, 1 movieId and 1 studioId. But this post works fine with postman...So what is it postman does that I have not included here? :) Commented Feb 1, 2020 at 8:40

1 Answer 1

2

I can see a couple of problems here:

  1. You are using both the body of the request and in the URL query.
  2. You're missing some important attributes in the control method signature .

I personally always try to use a single approach (either body or URL query). I find that it keeps the code more readable and is less bug-prone.


First of all, decide how you want to pass the data:

  • Through the request body
  • In the URL query
  • Mixed approach

Then write your methods accordingly.


In the body

The easiest approach is encapsulating your information in a .Net object and Jsonify its fields in the JavaScript:

public class RentDetails
{
    public int MovieId {get; set;}
    public int MaxRents {get; set;}
    public Studio {get; set;} // you can also use objects, deserializing the Json will fill them as well.
}

Then you want to specify in the signature of your method that you are receiving a RentDetails in the body of the request.

[HttpPost("save")]
public ActionResult<Rented> SaveRent([FromBody] RentDetails rentDetails) { ... }

And lastly, you want the Jsonified body to reflect the object that should be received (pay attention to field names):

const request = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                movieId : movieID, 
                maxRent : maxRent, 
                studio: 
                { 
                    // nested fields for nested objects
                } 
            })
        };

If you follow these steps, your controller will automatically deserialize the json in the body to the object and it will be ready for you to use.


In the URL Query

This is easier to handle but might grow to be messy.

Concatenate the fields in the javascript how you were already doing:

const link = baseLink.concat('?movieId=', movieId, '&maxRent=', maxRent, ...);
const result = await fetch(link); // no request is needed here, you already have all you need.

And then access those fields from the controller:

[HttpPost("save")]
public ActionResult<Rented> SaveRent() //<- no parameters are needed here 
{
    var allUrlKeyValues = HttpUtility.ParseQueryString(Request.QueryString.Value);
    var movieId = int.Parse(allUrlKeyValues["movieId"]);
    var maxRent = int.Parse(allUrlKeyValues["maxRent"]);
    ....
    // as you see you can only pass strings in this way
}


Mixed Approach

Of course you can opt for a mixed approach, just use a combination of the code above.

Note that the simpler, the better ;).

Sign up to request clarification or add additional context in comments.

1 Comment

Your encapsulating method worked like a charm! I also think I understand fetch a little better now too, thank you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.