I'm using js fetch to call to an action method(in asp.net mvc),
but I need to pass parameters to the method.
How can I pass this data using fetch?
I'm trying to use this code but the data didn't pass:
fetch(url, {
data: { repositoryName: "dada" }
})
.then(() => {
console.log("test");
});
According to the documentation second parameter shouldn't contain data property.
I guess you need to use body property(you can use JSON string, FormData or URLSearchParams here basing on your needs, see docs):
fetch(url, {
method: "POST",
body: JSON.stringify({ repositoryName: "dada" })
}).then(() => { ... })
Also in this simple example it's possible to simply use query string like this:
fetch(url + '?repositoryName=dada').then(() => { ... })
Note that GET requests cannot have body so if your MVC action is GET action then you have to use query strings like in my second example.
Related
I'm new to Web programming, and I wanted to know how to make easy requests to connect to an API if the only information I have are the URL, a login and password using pure Typescript or Javascript.
The goal is to retrieve an access Token.
I would advise using the browsers fetch API which uses promises.
let us begin here. In the past browsers offered AJAX calls but ever since modern JS came through with promises, everything got really easy. You can find out more about promises here.
let us consider an example similar to your case where you have a url endpoint, and some data you want to send to the url. we expect that the url with respond with a JSON payload containing a token.
// so we will define our constants here
const url = 'http://localhost/login';
const username = 'username';
const password = 'password';
// now we configure the fetch request to the url endpoint.
// we should probably put it inside a separate function since
// you're using a browser, you probably will bind this request
// to a click event or something.
function login() {
return fetch(url, {
// in the case of a login request most APIs use the POST method offered by
// RESTful APIs
method: 'post', // can be 'get', 'put', 'delete', and many more
// now we set any needed headers specified by the API
headers: {
// most APIs I have worked with use
'Content-Type': 'application/json',
// but some might need more, they will specify anyway.
},
// because we are using the 'post' method then we will need to add
// a body to the request with all our data, body excepts a string so
// we do the following
body: JSON.stringify({
username: username,
password: password,
}),
})
// Now we handle the response because the function returns a promise
.then((response) => {
// An important thing to note is that an error response will not throw
// an error so if the result is not okay we should throw the error
if(!response.ok) {
throw response;
}
// since we expect a json response we will return a json call
return response.json();
})
}
now since you are using a browser you will have to bind the function to
an element to trigger the call
// will define a self calling arrow function that will do the event binding
((button) => {
button.addEventListener('click', (event) => {
// we then call the function here.
login()
.then((response) => {
// side note, you could destructure the response argument as { token }
// then just reference token instead.
// recall that we expect this function to have a 'token' key in
// the response payload...so let us log it just to make sure
console.log(result.token);
})
});
// we add the button reference as the argument
})(document.querySelector('#submit'));
References:
Promises
RESTful
I hope this helps give a better idea on the task you have, good luck
u can use axios for js/ts
like this example :
getToken = () => {
axios.post('http://localhost/login',{
username: username,
password: password,
}).then((response) => {
let data = response.data;
//do whatever u want here eg :set token to local storage
localStorage.set('token',data.token);
}).catch((error) => {
console.log(error);
});
};
getToken();
I want to post with the Fetch API and call an action from my controller but the action is not being loaded like when I would do it with submitting a post form.
function postQuery() {
let query = document.getElementById("query").value;
fetch('/actionName', {
method: 'POST',
body: query,
headers:
{
"Content-Type": "application/x-www-form-urlencoded"
}
})
.then(response => {
console.log(response);
})
.then(data => {
console.log('Success:', data);
})
}
/actionName is not being loaded, I am supposed to be directed to a different page.
When I would submit a form like that:
<form action="/actionName" method="post">
the public function actionName would be called but with fetch its not working.
When i try to see the $_POST with var_dump($_POST) inside of actionName, I am getting an empty array...I dont understand this
I see two questions here:
Why is the data not accessible to the server
Why is the brower not redirected to /actionName
Answer to #1:
Make sure the content type header matches the data you are sending, if it is raw json, you should use application/json rather then application/x-www-form-urlencoded. If you want to send a form using fetch API, you would need to either serialize to form to a URL encoded format, or use FormData, for example:
var fd = new FormData(document.getElementById('myForm'))
fetch('/actionName', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data;'
},
body: fd
})
Answer to #2:
Submitting HTML Forms will direct the browser to the forms action, so if I submit a form to /actionName, I will end up seeing the HTML that is returned by the server for that route. Using Fetch API to submit a form is a type of AJAX, which means that it is capable of communicating with the server without needing to load a new page.
With that in mind, you have a few options:
Use a regular form so that the desired default behavior happens
Manually redirect the user somewhere after the fetch promise resolves, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
window.location.href = '/otherPage'
})
Render the response HTML without redirecting the user, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
data.text().then(rawHTML => {
document.body.parentElement.innerHTML = rawHTML
})
})
My personal intuition would be to go with the first option, as it suits your requirements and is the simplest.
I'm using the React template when creating a new project in Visual Studio. It has something like this for GET request:
fetch('api/SampleData/WeatherForecasts')
.then(response => response.json())
.then(data => {
this.setState({ forecasts: data, loading: false });
});
I'm learning how to do a POST request, so I modified the code to:
const formData = new FormData();
formData.append('values', this.state.values);
fetch('api/SampleData/WeatherForecasts', {
method: 'POST',
body: formData
}).then(response => response.json())
But not sure how to retrieve the formData on ASP.Net:
[HttpPost("[action]")]
public string WeatherForecasts()
{
// How to print out the values from formData here
// System.Diagnostics.Debug.WriteLine(Request.Form.ToString());
return "Hello";
}
Edit: I also don't know how to return a Json result from ASP.Net:
[HttpPost("[action]")]
public JsonResult WeatherForecasts()
{
// How to print out the values from formData here
// System.Diagnostics.Debug.WriteLine(Request.Form.ToString());
// How to return a Json here
// return {hello: 'Hello'};
}
My answer presumes that your this.state.values property contains a string for testing purposes only just like the following:
this.setState({
values: 'testingtext'
});
I guess you are on the right track, from front-end side I assume the data is being sent. You can additionally check in the browser's network tab how the data has been passed in the HTTP request's body.
I would modify the WeatherForcecasts() action as the following to capture the data on the back-end side:
[HttpPost]
public string WeatherForecasts([FromBody] string values)
{
// here you can check what has been passed to the values variable
return values;
}
About [FromBody] why you need to include into the attribute:
By default, Web API tries to get simple types from the request URI. The FromBody attribute tells Web API to read the value from the request body.
Source: Sending Simple Types
If you want to override the action name in your route then you can achieve that by adding into your method the [ActionName("YOUR_NEW_ACTION_NAME")] attribute but it is not a mandatory one:
You can override the action name by using the [ActionName] attribute.
Source: Routing by Action Name
I hope this helps! I guess this gives you an idea how to proceed further.
I want to use fetch() to query an API endpoint which powers my search page. It returns a list of search results in JSON format.
I also want to pass to the API the current query submitted by the user. The old implementation used jquery and getJSON. Looking at the docs for getJSON, it says that I can pass in a data variable:
data
Type: PlainObject or String
A plain object or string that is sent to the server with the request.
Looking at the docs for fetch, I'm not sure how to pass in data as part of my request. So my question is, how do I pass in a string that will be sent to the server along with my request?
EDIT: I think I can append the query to the request URL, like "/search/?q=Something" and send that. Does anyone have a better way?
If you look at the Body section of the documentation on fetch, it lists several types of values you can use to specify the data sent in your request.
Example using FormData:
var fd = new FormData();
fd.append('q', 'Something');
fetch('/search', {
method : "POST",
body : fd
})
.then(...)
Note that you can't use the body option on GET or HEAD requests (which it seems you may be doing in your case). In that situation, you can build up the parameters using URLSearchParams:
var params = new URLSearchParams();
params.append('q', 'Something');
fetch('/search/?' + params.toString(), {
method: 'GET'
})
.then(...);
You can pass as below
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
I recently found myself converting a function that calls a remote API, from returning a callback to returning a Promise. I thought that'd be a great opportunity to also replace the $.ajax call with a fetch call, as fetch already returns a Promise.
However, this specific call is a GET that actually expects a payload (containing key and return type). Specifically, I call it using:
$.ajax({
type: 'GET',
contentType: 'application/json; charset=utf-8',
url: config.serviceUrl,
data: {
apiKey: key,
format: 'json'
}
})
.done(data => {...})
.fail((jqXHR, textStatus, errorThrown) => {...});
However, fetch does not have a data property, and it throws an error if you try to send a body with a GET request (TypeError: Failed to execute 'fetch': Request with GET/HEAD method cannot have body). And according to the Chromium forums this is the expected behavior.
Bear in mind: I have absolutely no control of the external API, so mentioning that sending a payload with GET violates some API protocol, or suggesting I change the underlying call, is not helpful.
Is it possible to use fetch in this scenario? How?
jQuery's ajax function simply appends data to the URL as URL parameters for GET requests:
data
Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.
Source
Using fetch, you can either do it manually, or you could use an approach similar to that:
var url = new URL("http://youapi.com")
var data = {
apiKey: key,
format: 'json'
}
Object.keys(data).forEach(key => url.searchParams.append(key, data[key]))
fetch(url)
var headers = new Headers();
headers.append("Content-Type", "application/json; charset=utf-8");
fetch(config.serviceUrl + "?apiKey=" + key + "&format=json",
{headers:headers, method:"GET"}
).then(response => response.json())
.then(json => /* do stuff with `json` */)
.catch(err => console.error(err));
is equivalent to current $.ajax() call.