I need to post form data as below to URL which is a webapi and the method is post
var surveyData = {
Name: xyz,
SetReminder: 'false',
NoOfReminder: '0',
StartDate: 'xyz',
EndDate: 'xyz',
Language: 'eng-us',
Duration: '1',
ApplicationName: 'xyz',
SurveyTypeName: 'zxy'
};
i have written the below code which call the post method of wbeapi but the function is able to send the data but the post method is not able to read the data that is send using the angular js.
function(surveyData) {
return $http.post(URL , surveyData,{
headers: { 'Content-Type': 'multipart/form-data' }
});
Use :
var data = HttpContext.Current.Request.Form["surveyData"];
To recieve the json data from your multipart form.
If your multipart form contail files, then to get these files use :
System.Web.HttpFileCollection postedfiles = System.Web.HttpContext.Current.Request.Files;
Also keep in mind that do not use any parameter in your controller action method.
Make sure you import these namespaces:
using System.Net.Http;
using System.Web;
using System.Web.Http;
EDIT :
modify your javascript code.
var data = new FormData();
data.append("surveyData", angular.toJson(surveyData));
If you want to add images/other, you can add those using the code
below.
//data.append("uploadedFile", $scope.files[0]);
So your code will be :
function(surveyData) {
return $http.post(URL , data,{
headers: { 'Content-Type': 'multipart/form-data' }
});
Now you will be able to receive the json data using
var data = HttpContext.Current.Request.Form["surveyData"];
and images/otherfiles(If you have) using
System.Web.HttpFileCollection postedfiles = System.Web.HttpContext.Current.Request.Files;
if web api is Multipart/form-data then you need to create key value pair in the below form so that multi part form data will be created.
var objFormData = new FormData();
for (var key in surveyData)
objFormData.append(key, surveyData[key]);
then you need to send the created multi part form data using the below code:
return $http.post(URL, objFormData, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
});
Related
i am assigning an array to a key which need to be send in the payload of POST call in my angular js application. for example like below.
this.selectedCtlIds =[877, 982, 091, 112];
function saveFormSettings() {
let data = this.settings; // have various key from the GET call
data.statusIdToBeChanged = this.selectedCtlIds;
console.log(data.statusIdToBeChanged, 'test '); // works fine
Service.updateSettings(data).then(function (resp) {
//POST CALL HERE
}
}
function updateSettings(param) {
return $http({
method: 'POST',
url: url + '/setting',
params: param
})
}
expected payload by api is like statusIdToBeChanged: [877, 982, 091, 112]
instead it is passed like below when i checked in network payload
statusIdToBeChanged[]: 284
statusIdToBeChanged[]: 982
statusIdToBeChanged[]: 091
statusIdToBeChanged[]: 112
due to which the api is failing. i am not sure why it is like this in payload.
I want to post form data to a server that accepts and returns text/html/xml. I am effectively trying to emulate a normal URL encoded form POST. My Angular 8 POST function successfully posts (200 OK), but the server can't understand the data because it is JSON and not URL encoded.
Response and request headers state Content-Type: text/html; Charset=utf-8 and Accept: text/html, application/xhtml+xml, */* and I have added responseType: "text" to the httpClient options. Why is the server still being sent JSON and not URL encoded data?
// obj2 = output from ngForm
// baseUrl2 = server that sends and receives text/html/xml
public postForm(obj2) {
return this.httpClient
.post(this.baseUrl2, obj2, {
headers: new HttpHeaders({
"Content-Type": "application/x-www-form-urlencoded",
Accept: "text/html, application/xhtml+xml, */*"
}),
responseType: "text"
})
.map(data => data);
}
Form data sent:
{"Form data":{"{\"personsNameText\":\"name9\",\"centreEmailAddressText\":\"name9#name.com\",\"centreTelephoneNumberText\":123456789,\"centreNumberText\":\"ab123\",\"centreNameText\":\"ab123\",\"invoiceText\":\"123456789\",\"currencyText\":\"GBP\",\"amountText\":\"100\",\"cardtypeText\":\"Credit card\",\"commentsText\":\"Comments.\",\"declarationText\":true}":""}}
What I want:
personsNameText=name9?centreEmailAddressText=name9#name.com?centreTelephoneNumberText=123456789?centreNumberText=ab123?centreNameText=ab123?invoiceText=123456789?currencyText=GBP?amountText=100?cardtypeText=Credit card?commentsText=Comments.?declarationText=true
I'm not sure of the type of the obj2 object here but I'll assume it's somethings like
interface UserFormData {
['Form data']: { [name: string]: value };
}
You would need to transform this to FormData before posting it. Something along the lines:
const formEncodedObj2 = new FormData();
const obj2Keys = obj2['Form data'];
Object.keys(obj2Keys).forEach(key => formEncodedObj2.append(key, obj2Keys[key]));
And then send the formEncodedObj2 object.
So, this solution solved various problems for me:
Posting x-www-form-urlencoded data using Angular 8's forms and HttpClient
Correcting unwanted encoded characters
My specific problem was that a unique verification string contained ampersands that were being converted to HTML entities, i.e. & to &.
// userdata.service.ts
public postForm(obj) {
return this.httpClient
.post(this.baseUrl2, obj, {
headers: new HttpHeaders({
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Referer": "http://referer.com" // Replace with your own.
}),
responseType: "text"
})
.map(data => data)
.pipe(
retry(1),
catchError(this.handleError)
);
}
// app.component.ts
PostForm(userdata) {
// Stringify and convert HTML entity ampersands back to normal ampersands.
const corrected = JSON.stringify(userdata).replace(/(&)/gm, '&');
// Convert back to JSON object.
const corrected2 = JSON.parse(corrected);
// entries() iterates form key:value pairs, URLSearchParams() is for query strings
const URLparams = new URLSearchParams(Object.entries(corrected2));
// Convert to string to post.
const final = URLparams.toString();
// Post it
this.userdataService.postForm(final).subscribe(reponse2 => {
console.log(reponse2);
});
}
URLSearchParams() was the breakthrough and, as Vlad suggested, being absolutely sure of the type one is dealing with. I should have used Types to avoid confusion. I probably should use Angular Interceptors to deal with the character manipulation.
I have a service with the method which gets three parameters which should be sent to the server.
setMainPhotoFor: function(file, petName, petId) {
...
}
I have the following solution:
Client side
services.js
setMainPhotoFor: function(file, pet) {
var baseServerApiUrl = configuration.ServerApi;
var data = new FormData();
data.append("image", file);
data.append("petName", pet.Name);
data.append("petId", pet.ID);
$http.post(baseServerApiUrl + '/pictures/main-picture/add', data, {
headers: { "Content-Type": undefined }
});
}
Server side
PicturesApiController
[HttpPost]
[Route("main-picture/add")]
public async Task<HttpResponseMessage> SetMainPicture()
{
if (!Request.Content.IsMimeMultipartContent())
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
MemoryStream mainPicture = new MemoryStream(await provider.Contents[0].ReadAsByteArrayAsync());
string petName = await provider.Contents[1].ReadAsStringAsync();
int petId;
if (!int.TryParse(await provider.Contents[2].ReadAsStringAsync(), out petId))
{
//...
}
//...
But in my opinion it doesn't look good. Can anybody suggest a right and more elegant solution for this task?
to send multipart form with angular add th options like this:
$http.post(baseServerApiUrl + '/pictures/main-picture/add', data, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
});
I have answered this before here with server side sample code.
Basically you should stream the content and put your dto in a header. I've tried many ways and this is the best way in my opinion.
I'm developping an app, in which I want to be able to upload a photo to the backend (restframework + django).
For the backend side, I followed this tutorial.
When I use :
curl --verbose --header "Authorization: token {TOKEN}" --header "Accept: application/json; indent=4" --request POST --form photo=#/home/.../uyuni.jpg {DOMAIN}/api/users/1/photo/
This works perfectly, the file is really created, and I can retrieve it afterwards, using ng-src.
Then, I want to wire frontend to upload photo.
Here I tried lots of ideas from forums or tutos like this one
I have two different issues.
If I copy the last tuto, I end up with a 400 Bad Request:
Erreur d'analyse XML : aucun élément trouvé Emplacement : moz-nullprincipal:{1b4583fc...} Numéro de ligne 1, Colonne 1 :
I don't know if it comes from backend or mozilla. I read about CORS issue, but this shouldn't be a problem, as I use ionic proxy.
If I wire with cordova-plugin-camera, I have an URL (file:///home/.../example.jpg) returned, I don't know how to wire this to the FormData to use for the POST to the backend:
var updateUserPhoto = function (userId, photoURI) {
if (!photoURI) {return}
var fd = new FormData();
fd.append('photo', photoURI);
return $http.post(API_URL + "users/"+userId+"/photo/", fd, {
transformRequest: angular.identity,
headers: {AUTHORIZATION: "Token "+window.localStorage['apiToken'], 'CONTENT-TYPE': undefined}
});
};
I tried to append an object in fd, like {path: photoURI, name: 'blablabla'}
In this issue, I end up with a Django error:
AttributeError at /api/users/1/photo/ 'str' object has no attribute 'name'
I'm probably not that far, so I'd rather not use external snippets.
I had very similar issues, and then some. This Media plugin from the Ionic marketplace resolved the issue by providing both base64 data as well as uri for me to use.
I finally solved my issue. Ouf!
I used this on backend side:
import base64
from django.db.models import ImageField
from django.db.models.fields.files import ImageFieldFile
from django.core.files.uploadedfile import InMemoryUploadedFile
def upload_to(instance, filename):
return 'profiles/' + filename
def wrap(content):
class File(InMemoryUploadedFile):
def read(self):
return base64.b64decode(super().read())
return File(content.file, content.field_name, content.name, content.content_type, content.size, content.charset)
class Base64ImageFieldFile(ImageFieldFile):
def save(self, name, content, save=True):
super().save(name, wrap(content), save=True)
class Base64ImageField(ImageField):
attr_class = Base64ImageFieldFile
And on frontend side:
To configure my resource:
var userActions = getActions(User);
var updatePhotoHeader = angular.copy(auth_header);
updatePhotoHeader['CONTENT-TYPE'] = undefined;
userActions['updatePhoto'] = {
method: "POST",
url: API_URL + "users/:userId/photo/",
params: {userId: "#userId"},
headers: updatePhotoHeader,
transformRequest: function (data) {
if (!data) {return}
var fd = new FormData();
fd.append('photo', new Blob([data.photo], {type: 'image\/jpeg'}));
return fd
}
};
with this options for the camera (from cordova plugin):
var cameraOptions = {
quality: 75,
destinationType: 0,
targetWidth: 750,
targetHeight: 500,
saveToPhotoAlbum: false,
cameraDirection: 1,
allowEdit: true,
encodingType: 0 // 0=JPG 1=PNG
};
PS: This solution might not be the best. Still hope to find a better one. But I will go on with this for now.
I have a post request I am doing like so:
var addProject = function (project, id) {
return $.ajax(projectUrl, {
type: "POST",
data: { project: project, id: id }
});
};
This is all fine, and it send up my project object (in JSON) with no problem. What i want to do is this request but also add in a key (that does not belong in the project object) that I can pass to the server controller. Any idea if I can do this, or what is a good way to do this. I really don't want to have to go back and change my object models to account for a key that I will only need every once in awhile.
This is an ASP.NET MVC4 project, and it is going back to a web api controller if that matters.
EDIT: here is my server side stuff
public HttpResponseMessage PostNew(Project project, int id)
{
//TODO grab the client to add the project to
Uow.Projects.Add(project);
Uow.Commit();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, project);
//response.Headers.Location = new Uri(Url.Link("ApiControllerAction", new { id = client.ID }));
return response;
}
Maybe I am not being clear enough. I want to pass in the project object, and then just an int variable. Passing project alone works, but if I try to pass the int it gives me a 400 error
var addProject = function (project) {
return
$.ajax(projectUrl, {
type: "POST",
data: {data1 : 'Object',data2: 'variable'}
});
};
You have just to send 2 data params., object and var..
Easiest way to pass a complex object is to JSON-encode it:
var addProject = function (project) {
return $.ajax(projectUrl, {
type: "POST",
contentType: 'application/json',
data: JSON.stringify(project)
});
};
To decode this on the server side, you will need a JSON decoder of some kind. I'm sure C# has some available.