I have an issue with fetching and passing data to ASP.NET web service from ReactJS.
Other fetch function is working when only getting data from the database.
Why am I getting these errors ? what am I doing here wrong ?
I believe its something in my signUp fetch function.
That response I think is that the fetch can't read the response from the server -
main.chunk.js:2417 POST http://localhost:50496/WebService.asmx/SignUp 500 (Internal Server Error)
SyntaxError: Unexpected token T in JSON at position 0 at JSON.parse (<anonymous>)
ReactJS
userData = {
fName: 'some',
lName: 'two one',
email: 'someonw#gmail.com',
password: 'se123456' }
My fetch function in ReactJs -
const signUp = (signUpData) => {
let data = {
firstName: signUpData.fName,
lastName: signUpData.lName,
emailAddress: signUpData.email,
password: signUpData.password,
};
fetch('http://localhost:50496/WebService.asmx/SignUp', {
body: JSON.stringify(data),
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.text())
.then(
(xml) =>
new window.DOMParser().parseFromString(xml, 'text/xml')
.documentElement.firstChild.textContent
)
.then((jsonStr) => JSON.parse(jsonStr))
.then((userData) => {
if (userData.d && userData.d.length > 0) {
setUser(userData);
} else {
console.log('error no data');
}
})
.catch((err) => {
console.log(err);
});
};
Error from Chrome -
System.InvalidOperationException: Missing parameter : firstName.
System.Web.Services.Protocols.ValueCollectionParameterReader.Read(NameValueCollection collection)
System.Web.Services.Protocols.UrlParameterReader.Read(HttpRequest request)
System.Web.Services.Protocols.HttpServerProtocol.ReadParameters()
System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
SignUp WebMethod is working in the WebService.
[WebMethod]
public string SignUp(string firstName, string lastName, string emailAddress, string password)
{
return BLL.SignUp(firstName, lastName, emailAddress, password);
}
I found What I needed to do,
another error was -
InvalidOperationException: Only web services with the [ScriptService]
attribute in the class definition can be read from a script.
So I added to WebService.cs the Attribute Class[ScriptService]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
And Since this completely eliminates the need to parse XML as you must when using standard SOAP (Simple Object Access Protocol) web services, I removed this code lines -
.then((response) => response.text())
.then(
(xml) =>
new window.DOMParser().parseFromString(xml, 'text/xml')
.documentElement.firstChild.textContent
)
.then((jsonStr) => JSON.parse(jsonStr))
And changed to this -
.then((response) => response.json())
.then((userData) => {
if (userData.d && userData.d.length > 0) {
let user = JSON.parse(userData.d);
setUserData(user);
}
Related
I'm work on chat app between specific clients using Angular and SignalR. So far everything is working good except one thing - when I'm sending a message to specific user, I want to send it also to myself.
After a lot reading of reading, I've realized that I can't get the Context value unless I'm approaching directly to my hub. I found a way to go around it by invoking GetSenderName() method (to get the sender's name) and then send it back to the server's controller. The problem is when I've added the parameter fromUser to my request . Before I've added it the request, I've reached the server and after I've added it I'm getting-
Status code 400
I've tried to debugg the client and it seems like all the parametrs has a valid values so I don't understand what went worng. Can anyone help me please?
User component (only the relevant part)-
fromUser: string="";
sendMessageToUser(sendToUser: any): void {
this.sendToUser=sendToUser;
this.fromUser=this.signalRService.getName();
console.log("fromUser: ", this.fromUser);
console.log("check sendToUser: ", this.sendToUser);
this.signalRService.sendMessageToUser(
this.sendMessageToUserUrl,
this.chatMessage,
this.sendToUser,
this.fromUser
);
}
SignalR Service-
public fromUser: string="";
constructor(private http: HttpClient) { }
public startSignalrConnection(connectionUrl: any) {
return new Promise<any>((resolve, reject) => {
this.hubConnection = new HubConnectionBuilder()
.withUrl(connectionUrl, {
withCredentials: false,
accessTokenFactory: () => localStorage.getItem('jwt')!,
})
.configureLogging(LogLevel.Debug)
.build();
this.hubConnection.start()
.then(() => {
console.log('in');
resolve(this.hubConnection.connectionId);
})
.then(()=>this.getSenderName())
.catch((error) => {
reject(error);
});
public getSenderName=()=>{
this.hubConnection.invoke('getSenderName')
.then((data)=>{
console.log("this is the data: ", data);
this.fromUser=data;
})
}
public getName(): string{
return this.fromUser;
}
This is where the problem is (SignalR Service)-
public sendMessageToUser(sendMessageToUserUrl: string, message: string, sendToConnId: any, fromUser:string){
firstValueFrom(this.http.post(sendMessageToUserUrl, buildChatMessageModel(sendToConnId, message, fromUser)))
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log("Failed to send message: ", error);
alert("Failed to send message: "+ error);
})
}
ChatMessageModel-
export interface ChatMessageModel {
ConnectionId: string,
Message: string
FromUser: string
}
Utils-
export const buildChatMessageModel = (hubConnectionId: string, message: string, fromUser: string): ChatMessageModel => {
return {
ConnectionId: hubConnectionId,
Message: message,
FromUser: fromUser
};
};
First time working with web APIs and I can't seem to make the PUT method work, while everything works fine (get, post and delete).
I'm trying to do, what I think it is, a very simple call to update testimonials. These will have an image file, name and text. The problem is I'm getting error 400 when trying to update them using a PUT call.
I'm using FormData to send the data since I need to also send the image file and the rest of the form (the URI is "/api/testimonials", and the Id is a guid):
function updateItem() {
const itemId = document.getElementById('edit-id').value;
const item = {
id: itemId,
name: document.getElementById('edit-name').value.trim(),
text: document.getElementById('edit-text').value.trim(),
};
const formData = new FormData();
formData.append('file', document.getElementById('edit-file').files[0]);
formData.append('jsonString', JSON.stringify(item));
fetch(`${uri}/${itemId}`, {
method: 'PUT',
contentType: 'false',
processData: 'false',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: formData
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));
closeInput();
return false;
}
and this is the method in the TestimonialsController:
[HttpPut("{id}")]
public async Task<IActionResult> PutTestimonial(string id, [FromForm] IFormFile? file, [FromForm] string jsonString)
{
...
}
Other methods like POST and Delete, that also pass an Id or data work just fine, but PUT is not being called.
POST method
[HttpPost]
public async Task<ActionResult<TestimonialDTO>> PostDepoimento([FromForm] IFormFile? arquivo, [FromForm] string jsonString)
{
...
}
function addItem() {
const addNameTextbox = document.getElementById('add-name');
const addTextTextbox = document.getElementById('add-text');
const item = {
name: addNameTextbox.value.trim(),
text: addTextTextbox.value.trim(),
};
const formData = new FormData();
formData.append('file', document.getElementById('add-file').files[0]);
formData.append('jsonString', JSON.stringify(item));
fetch(uri, {
method: 'POST',
contentType: 'false',
processData: 'false',
body: formData
})
.then(response => response.json())
.then(() => {
getItems();
addNameTextbox.value = '';
addTextTextbox.value = '';
})
.catch(error => console.error('Unable to add item.', error));
}
DELETE method
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTestimonial(string id)
{
...
}
function deleteItem(id) {
fetch(`${uri}/${id}`, {
method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));
}
Could you help me identify why is the PUT method not being called? Is there anything wrong in the way I'm calling the method/passing data?
400 error is because [FromForm] does not allow application/json Content-Type. Just remove the header in your updateItem function:
headers: {
'Accept': 'application/json',
//'Content-Type': 'application/json'
},
FromForm occurs at the parameter binding stage, which is part of the request pipeline that necessarily occurs before entry into the endpoint. This is why under debug, for example, your breakpoints wouldn't hit.
I have a /services/userService.js file in Nuxt 3:
const baseURL = 'http://localhost:8080/api/auth/'
const headers = {
Accept: 'application/json',
'Content-type': 'application/json',
}
export default {
signinNewUser(firstName, secondName, email, password) {
return useFetch('/signup', {
method: 'POST',
baseURL: baseURL,
headers: headers,
body: {
firstName,
secondName,
email,
password,
},
})
},
}
And I have the following function in /store/user.js
async registerUser(firstName, secondName, email, password) {
return userService
.signinNewUser(firstName, secondName, email, password)
.then(
(res) => {
const data = res.data.value
const error = res.error.value
if (error) {
console.log(error)
} else {
this.registered = true
}
},
(error) => {
console.log('exception...')
console.log(error)
}
)
},
My auth API can answer with a 400 status code and different error messages in the response body like:
{"message":"Error: Email is already in use!"}
{"message":"Error: FirstName is already in use!"}
etc...
I want to be able to access those messages in order to show to the user different error messages so he/she knows how to fix the issue.
How can I achieve that?
I tried accessing the error object but it doesn't contain a reference to the response body, data object is null
You can access the body of the error response using the data key from the error reference object. An http error will not always raise an error in the composable.
const data = error.value.data;
async registerUser(firstName, secondName, email, password) {
return userService
.signinNewUser(firstName, secondName, email, password)
.then(
(res) => {
const data = res.data.value
const error = res.error.value
if (error) {
console.log(error)
this.error = error.data; // <== To handle the error data.
} else {
this.registered = true
}
},
(error) => {
console.log('exception...')
console.log(error)
}
)
},
Also, the useFetch composable allows you to use interceptors to access the data in an other fashion, please refer to the documentation on the subject.
I have done logging-in WordPress Rest API with JWT Plugin passing administrator account and password and stores the received token in AsyncStorage like this.
await AsyncStorage.setItem(
'user',
JSON.stringify({
token: userData.token,
user_email: userData.user_email,
user_nicename: userData.user_nicename,
user_display_name: userData.user_display_name,
}),
);
Then I manage to get all posts including private post by including the token with request header like this,
let userInfo = await AsyncStorage.getItem('user');
let jsonUser = await JSON.parse(userInfo);
let credential = 'Bearer ' + jsonUser.token;
fetch('http://localhost/reactnativewordpress/wp-json/wp/v2/posts', {
headers: {
Authorization: credential,
},
method: 'GET',
withCredentials: true,
credentials: 'include',
})
.then(response => response.json())
.then(responseJson => {
this.setState({
items: responseJson
});
})
.catch(error => {
console.log('Error :' + error);
});
The responseJson have only public posts, no private post at all.
Thanks for help.
You need to add the
status=private
in your request,
like this http://localhost:8000/wp-json/wp/v2/posts?status=private
With that, the Authorization header should run ;)
I'm struggling to figure out why the response I get from my API isn't mapping to an object that I have in typescript.
Here's the function in my service that calls the API:
register(user: IUser): Observable<IUser> {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
var options = new RequestOptions({
headers: headers,
url: this._registerUrl,
body: JSON.stringify(user)
});
return this._http.post(this._registerUrl, { user }, options)
.map((res: Response) => res.json() as IUser)
.catch(this.handleError);
}
This is the function that calls the service:
register(): void {
let user: IUser = {
email: this.email,
username: this.username,
password: this.password
}
this._userService.register(user)
.subscribe(result => {
debugger;
if(result.errorCode > 0)
this.handleError(result.errorCode);
else {
localStorage.setItem('userId', result.userId.toString());
localStorage.setItem('username', result.username.toString());
localStorage.setItem('email', result.email.toString());
}
});
}
The object that I am returning from the API matches the object that I have in the frontend. It is returning the data and I can see it in the body of my response. All of the data is right, but it's in the body and is not turning it into an IUser object.
Does anybody have any ideas? Thanks.
EDIT
This is what the response object looks like when it comes back from the service.