I'm posting some formData from my Angular 5 app to my Web API. Here's the typescript code:
public postFormData() {
const form = $('#customListForm')[0];
const formData = new FormData();
formData.append('tenant', form[0].value);
formData.append('username', form[1].value);
formData.append('password', form[2].value);
formData.append('CL_title', form[3].value);
formData.append('CL_description', form[4].value);
formData.append('CL_contentType', form[5].value);
formData.append('CL_template', form[6].value);
// const json = JSON.stringify(formData);
this.http.post(this.apiURL, formData, this.httpOptions).catch(this.errorHandler).subscribe(res => this.formPosted(res));
// this.http.get(this.apiURL).catch(this.errorHandler).subscribe(res => this.formPosted(res));
}
Here's my httpOptions:
private httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
})
};
I've tried various content types like application/json, or multipart/form-data but none work too.
Here's my Controller Post Action:
// POST api/customlist
[HttpPost]
public System.Web.Http.IHttpActionResult Post(CustomList data)
{
var test = HttpContext.Current.Request;
var testje = data;
return Ok("POST all good");
}
Here you can see my CustomList custom object:
public class CustomList
{
public CustomList()
{
}
public string Tenant { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string CL_title { get; set; }
public string CL_description { get; set; }
public string CL_contentType { get; set; }
public string CL_template { get; set; }
}
As you can see it contains the same fields as my formData & has a default/empty constructor.
No matter what I try, I always get my "data" to be null... Any ideas?
Related
I get each value but it doesn't display on DSChiTiet. How can I fix it? It only gets value TenKH, NgayLap, TongTien.
DSChiTiet doesn't get value from table and displays null. enter image description here
Thank you very much for your help <3.
My model PhieuBanHangModel
public class PhieuBanHangViewModel
{
public int MaPBH { get; set; }
public string TenKH { get; set; }
public DateTime NgayLap { get; set; }
public decimal TongTien { get; set; }
public IEnumerable<CT_PhieuBanHangViewModel> DSChiTiet { get; set; }
}
My model CT_PhieuBanHangModel
public class CT_PhieuBanHangViewModel
{
public int MaPBH { get; set; }
public int MaSP { get; set; }
public int SoLuong { get; set; }
public decimal DonGia { get; set; }
public decimal ThanhTien { get; set; }
}
Controller Create Json
[HttpPost]
public JsonResult Create(PhieuBanHangViewModel phieuBanHang)
{
return Json(data: "", JsonRequestBehavior.AllowGet);
}
Function in View
function ThanhToan() {
var phieuBanHang = {};
var dsct_PhieuBanHang = new Array();
phieuBanHang.TenKH = $("#txtTenKH").val();
phieuBanHang.NgayLap = $("#txtNgayGiaoDich").val();
phieuBanHang.TongTien = $("#txtTongTien").val();
$("table tr:not(:first)").each(function () {
var ct_PhieuBanHang = {};
ct_PhieuBanHang.MaSP = parseFloat($(this).find("td:eq(0))").text());
ct_PhieuBanHang.SoLuong = parseFloat($(this).find("td:eq(4))").text());
ct_PhieuBanHang.DonGia = parseFloat($(this).find("td:eq(6))").text());
ct_PhieuBanHang.ThanhTien = parseFloat($(this).find("td:eq(7))").text());
dsct_PhieuBanHang.push(ct_PhieuBanHang);
});
phieuBanHang.DSChiTiet = dsct_PhieuBanHang;
$.ajax({
async: true,
type: 'POST',
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(phieuBanHang),
url: '/Manager/CT_PhieuBanHang/Create',
success: function (data) {
},
error: function () {
alert('Lỗi');
}
});
}
You may need to inherit ApiControllerand add the [FromBody] attribute to the binding model:
public class MyController : ApiController
{
/* something else... */
// /Manager/CT_PhieuBanHang/Create
[HttpPost]
public JsonResult Create([FromBody] PhieuBanHangViewModel phieuBanHang)
{
return Json(data: "", JsonRequestBehavior.AllowGet);
}
/* something else... */
}
For your jQuery code, make sure thet:$("table tr:not(:first)") do returns an array contains at least 1 item. (You can verify that by doing a console.log(phieuBanHang) to print out your data).
I am sending formdata data object to mvc controller. I received the array in controller but the object is always missing. Searched a lot about it did not find a clue.
I have tried to send whole object or appending each value to formdata but its always null. does formdata accepts? nested object.
My jQuery code:
function addstudent() {
var form= $("#studentform").valid();
if (form)
{
personfood.details.firstname = $("#firstname").val();
personfood.details.lastname = $("#lastname").val();
personfood.details.imageuploaded = $("#imageupload")[0].files[0];
personfood.details.rememberme = $("#rememberme").is(":checked");
personfood.details.newsletter = $("#newsletter").is(":checked");
personfood.details.gender = $("input[name='gender']").val();
var personfoods = new FormData();
$.each(personfood.details, function (key, value) {
personfoods.append(key, value);
});
$.each(personfood.foodname, function (key, value) {
personfoods.append("foodname["+[key]+"]", value);
});
for (var pair of personfoods.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
$.ajax({
url: "/Main/addperson",
type: "POST",
processData: false,
cache: false,
contentType: false,
dataType: "json",
data: personfoods,
success: onsucessinsert,
error:onerrorinsert
})
}
My ViewModel
public class personfoods
{
public details details { get; set; }
public List<string> foodname { get; set; }
}
details model:
public class details
{
public int id { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string imagename { get; set; }
public string imageshorturl { get; set; }
public string imagefullurl { get; set; }
public bool rememberme {get;set;}
public bool newsletter { get; set; }
public string gender { get; set;}
public HttpPostedFileBase imageuploaded { get; set; }
}
i solve it using $.each and appending key value pairs to my formdata.
$.each(personfood.details, function (key, value) {
personfoods.append("details[" + key + "]",value);
});
ContentType should be ''application/json; charset=utf-8" and you can not post files like you are doing. I think data:JSON.stringify(personfoods); should work for remaining properties.
Using Visual Studio 2013 I've create a new Web API 2 project and a new MVC project. There will be other clients accessing the API which is the reason it was created. Eventually the clients for the API will be allowing users to create login account using Facebook and other.
The issue I'm running into to trying read an errors returned from the API during a login such as Bad Password. I've seen many, many posts about similar errors to "No MediaTypeFormatter is available to read an object of type something from content with media type 'text/html'." but cannot resolve this issue.
The API is only needs to return json so in my WebApiConfig.cs file is
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
Here is my post in Fiddler
Here is the Response:
and the Textview of the response which looks like json to me
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
Yoda test = new Yoda() { email = model.Email, password = model.Password };
HttpClient client = CreateClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//client.DefaultRequestHeaders.TryAddWithoutValidation("content-type", "application/x-www-form-urlencoded");
client.DefaultRequestHeaders.TryAddWithoutValidation("content-type", "application/json");
HttpResponseMessage result = await client.PostAsJsonAsync(_apiHostURL, test);
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
var token = result.Content.ReadAsAsync<TokenError>(new[] { new JsonMediaTypeFormatter() }).Result;
}
public class TokenError
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
[JsonProperty("error")]
public string Error { get; set; }
}
public class Yoda
{
public string email { get; set; }
public string password { get; set; }
public string grant_type
{
get
{
return "password";
}
}
}
The exact error is
"No MediaTypeFormatter is available to read an object of type 'TokenError' from content with media type 'text/html'. "
After much searching it appears there wasn't much wrong with my code except that the Token endpoint in Web Api doesn't accept json. I was playing in a console app.
using Newtonsoft.Json;
using System.Net.Http.Formatting; //Add reference to project.
static void Main(string[] args)
{
string email = "test#outlook.com";
string password = "Password#123x";
HttpResponseMessage lresult = Login(email, password);
if (lresult.IsSuccessStatusCode)
{
// Get token info and bind into Token object.
var t = lresult.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
}
else
{
// Get error info and bind into TokenError object.
// Doesn't have to be a separate class but shown for simplicity.
var t = lresult.Content.ReadAsAsync<TokenError>(new[] { new JsonMediaTypeFormatter() }).Result;
}
}
// Posts as FormUrlEncoded
public static HttpResponseMessage Login(string email, string password)
{
var tokenModel = new Dictionary<string, string>{
{"grant_type", "password"},
{"username", email},
{"password", password},
};
using (var client = new HttpClient())
{
// IMPORTANT: Do not post as PostAsJsonAsync.
var response = client.PostAsync("http://localhost:53007/token",
new FormUrlEncodedContent(tokenModel)).Result;
return response;
}
}
public class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("userName")]
public string Username { get; set; }
[JsonProperty(".issued")]
public DateTime Issued { get; set; }
[JsonProperty(".expires")]
public DateTime Expires { get; set; }
}
public class TokenError
{
[JsonProperty("error_description")]
public string Message { get; set; }
[JsonProperty("error")]
public string Error { get; set; }
}
//My web-service method WebService1.asmx
[WebMethod]
[ScriptMethod]
public string GetAllEvents()
{
var list = new List<string>();
list.Add("[{\"id\":\"36\"title\":\"Birthday party\",\"start\":\"2013-09-18\",\"end\":\"2013-09-18\",\"allDay\":false}]");
JavaScriptSerializer jss = new JavaScriptSerializer();
string strJSON = jss.Serialize(list.ToArray());
return strJSON;
}
//My jQuery snippet
$("#fullcalendar").fullCalendar({
eventSources:
[
{
url: "http://localhost:49322/WebService1.asmx/GetAllEvents",
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
}
]
});
You are on the wrong track.
Don't form your json strings manually using string operations (As in your case, it is an invalid json).
Don't return string from your web method, return the real object
It should be something like this:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<Event> GetAllEvents()
{
List<Event> events = .......
..fill the list....
return evetns;
}
public class Event
{
public int id { get; set; }
public string title { get; set; }
public string start { get; set; }
public string end { get; set; }
public bool allDay { get; set; }
}
I want to build an HTTP post that will send data and automatically bind the data into the model. I'm having an issue getting this to work, however, as the model comes up empty. I am using mvc 2.
My controller
[HttpPost]
public JsonResult Authenticate(AuthenticateRequest request)
{
//...do stuff
}
and here's how I am building the request.
private static string Url(string action, string controller)
{
return String.Format("{0}/{1}/{2}", Settings.Default.MobileServiceUrl, controller, action);
}
public static string Post(string action, string controller, NameValueCollection parameters)
{
string url = Url(action, controller);
using (WebClient client = new WebClient())
{
NameValueCollection fields = new NameValueCollection();
client.UploadValues(url, parameters);
byte[] respBytes = client.UploadValues(url, fields);
return client.Encoding.GetString(respBytes);
}
}
Here's the model class
public class AuthenticateRequest
{
public string SiteAbbreviation { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string AdminPassword { get; set; }
}
here is the sample data
NameValueCollection fields = new NameValueCollection();
fields.Add("SiteAbbreviation", "ABCD");
fields.Add("Username", "username");
fields.Add("Password", "password");
fields.Add("AdminPassword", "password");
var json = HttpRequestHelper.Post("Authenticate", "Account", fields);
var result = JsonConvert.DeserializeObject<AuthenticateRequest>(json);
EDIT:
If you are wondering why I am doing this, My mvc app is a rest api that returns json for everything. I am trying to build a test project to test my controller methods.
Assuming:
public class AuthenticateRequest
{
public string SiteAbbreviation { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string AdminPassword { get; set; }
}
and:
[HttpPost]
public ActionResult Authenticate(AuthenticateRequest request)
{
//...do stuff
}
the following should most definitely work:
using (var client = new WebClient())
{
var fields = new NameValueCollection
{
{ "SiteAbbreviation", "ABCD" },
{ "Username", "username" },
{ "Password", "password" },
{ "AdminPassword", "password" }
};
byte[] result = client.UploadValues(
"http://foo.com/someController/authenticate",
fields
);
// TODO: do something with the result
// if it is a JSON object deserialize it back to a model
}
Once you make sure that this works (and it should) you could start componentizing this code.
Got Error 404 in MVC 3. After removing the [HttpPost] attribute, the code above worked fine.