this opportunity Ii'd like to thank everyone who has an answer to this question, I'm trying to get a json from my web api service and I can't this is my code at the web api...
[ResponseType(typeof(List<CompanyType>))]
[Route("GetList")]
[DeflateCompression]
public async Task<IHttpActionResult> Get()
{
List<CompanyType> companyTypes = (List<CompanyType>)MemoryCacheManager.GetValue(#"CompanyTypes");
if (companyTypes != null) return Ok(companyTypes);
companyTypes = await _CompanyType.Queryable().ToListAsync();
if (companyTypes == null) return Ok(HttpStatusCode.NoContent);
MemoryCacheManager.Add(#"CompanyTypes", companyTypes);
return Ok(companyTypes);
}
and at the site of my client I got this
public async Task<T> GetAsync<T>(string action, string authToken = null)
{
using (var client = new HttpClient())
{
if (!authToken.IsNullOrWhiteSpace())
client.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse(#"Bearer " + authToken);
var result = await client.GetAsync(BuildActionUri(action));
string json = await result.Content.ReadAsStringAsync();
if (result.IsSuccessStatusCode)
return JsonConvert.DeserializeObject<T>(json); //This line fails because the characters in the value
throw new ApiException(result.StatusCode, json);
}
}
As you can see there nothing than weird here it is a simple code that try to parse a json value to a Generic class but this fails bacause when i call my webapi Url it gives me this value
json = ��VR�LQ�R2T�Q�2u�B*R�"E�e�)�#q�������̔Ԣb%��Ҝ�Z�>#�>#�>�̊B������J�r2�q�
I don't know why my webapi give me tha value, when I try to debug just my service it give me this value
<ArrayOfCompanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" ><CompanyType z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"><Id>1</Id><Type>Privada</Type><JobProviders i:nil="true" /></CompanyType><CompanyType z:Id="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"><Id>2</Id><Type>Mixta</Type><JobProviders i:nil="true" /></CompanyType><CompanyType z:Id="i3" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"><Id>3</Id><Type>Publica</Type><JobProviders i:nil="true" /></CompanyType></ArrayOfCompanyType>
as you can see everything looks fine but the problem start when I try to parse to get this value from my client.
this is my class
[DataContract(IsReference = true, Name = #"CompanyType", )]
public class CompanyType : Entity
{
[DataMember(Order = 0)]
public int Id { get; set; }
[DataMember(Order = 1)]
public string Type { get; set; }
[DataMember(Order = 2)]
public virtual List<JobProvider> JobProviders { get; set; }
}
I tried it without de DataContracts and still the same error.
best regards!.
Well I figured out, I was trying to use this sample http://blog.developers.ba/asp-net-web-api-gzip-compression-actionfilter/ but the thing was that the serializer wasn´t registered, so at my startup project I did this
GlobalConfiguration.Configuration.Formatters.Add(new ProtoBufFormatter());
And I changed my Actions deleting the attribute [DeflateCompression]
[ResponseType(typeof(List<CompanyType>))]
[Route("GetList")]
//[DeflateCompression]
public async Task<IHttpActionResult> Get()
{
Logic goes here....
}
And It's working now, but now I have another Issue and its when I try to make a call to my webapi action where I have to response an IHttpActionResult there is an exception of
no serializer defined for type: System.Object
Related
I have an Asp.net web api with one method that receive a crypted string with variable length, my problem is it string some times could take a length near 5000.
When that method receive a string under 1930 length it process everything ok, but for lengths over 1929 returns
404 Operation returned an invalid status code 'BadRequest'
I changed method GET to POST but problem persists.
I changed filter options on server to very very long limits, but problem persists
This is my controller:
public class LicencingManagerController : ApiController
{
[HttpPost]
[Route(nameof(SaveCustomer2))]
public string SaveCustomer2(string custInfo)
{
return $"ItsOk = {custInfo}";
}
}
Actually I made calls to controller using autogenerated c# client by AutoRest 2.0.483.
I tried hand building PostAsync Request using HttpClient but nothing works.
string custInfo = "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";
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("custInfo", custInfo)
};
var content = new FormUrlEncodedContent(pairs);
var client = new HttpClient();
// call sync
var response = client.PostAsync($"{Modelos.Shared.HttpsServicesReference.Licencing}/LicencingAPI/SaveCustomer2", content).Result;
if (response.IsSuccessStatusCode)
{
}
What is the right way to process this controller call?
There is another approach to perform this ?
Create model to hold data
public class Customer {
public string CustumerInfo { get; set; }
}
Update API to expect model in body of request
public class LicencingManagerController : ApiController {
[HttpPost]
[Route(nameof(SaveCustomer2))]
public IHttpActionResult SaveCustomer2([FromBody]Customer model) {
if(!ModelState.IsValid)
return BadRequest(ModelState);
var custInfo = model.CustumerInfo;
return Ok($"ItsOk = {custInfo}");
}
}
Post content to API in body of the request like you did before
string custInfo = "H4sIAAAAAAAEAA...";
string url = $"{Modelos.Shared.HttpsServicesReference.Licencing}/LicencingAPI/SaveCustomer2";
var pairs = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("CustumerInfo", custInfo)
};
var content = new FormUrlEncodedContent(pairs);
var client = new HttpClient();
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode) {
}
I want to know exactly why this is not working:
[HttpPost]
public IHttpActionResult Post(Slack_Webhook json)
{
return Ok(json.challenge);
}
public class Slack_Webhook
{
public string type { get; set; }
public string token { get; set; }
public string challenge { get; set; }
}
The Official Documentation says:
We’ll send HTTP POST requests to this URL when events occur. As soon
as you enter a URL, we’ll send a request with a challenge parameter,
and your endpoint must respond with the challenge value.
This is an example object (JSON) sent by Slack:
{
"token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
"type": "url_verification"
}
EDIT:
I could write a book on code that does not work in this issue... here's another example that did not work - still no idea what is wrong:
[HttpPost]
public IHttpActionResult Post()
{
var pairs = Request.GetQueryNameValuePairs();
bool isValidToken = false;
string c = "This does not work.";
foreach(var pair in pairs)
{
if (pair.Key == "token")
{
if (pair.Value == "<UNIQUETOKEN>")
{
isValidToken = true;
}
}
if (pair.Key == "challenge")
{
c = pair.Value;
}
}
if (isValidToken == true)
{
return Json(new {challenge = c });
}
else
{
return BadRequest();
}
}
EDIT2:
Very interesting that I get NULL as a response from below code - that means the body of the received POST is empty.. Could anyone with a working Slack-Integration try that out? So their site is wrong, stating the challenge is sent in the body - where else could it be?
// POST: api/Slack
[HttpPost]
public IHttpActionResult Post([FromBody]string json)
{
return Json(json);
}
EDIT3:
This function is used to get the raw request, but there is nothing inside the body - I am out of solutions.. the support of Slack said, they have no idea about ASP.NET and I should ask here on SO for a solution. Here we are again! ;-)
[HttpPost]
public async Task<IHttpActionResult> ReceivePostAsync()
{
string rawpostdata = await RawContentReader.Read(this.Request);
return Json(new StringContent( rawpostdata));
}
public class RawContentReader
{
public static async Task<string> Read(HttpRequestMessage req)
{
using (var contentStream = await req.Content.ReadAsStreamAsync())
{
contentStream.Seek(0, SeekOrigin.Begin);
using (var sr = new StreamReader(contentStream))
{
return sr.ReadToEnd();
}
}
}
}
The result ( as expected ) looks like this:
Our Request:
POST
"body": {
"type": "url_verification",
"token": "<token>",
"challenge": "<challenge>"
}
Your Response:
"code": 200
"error": "challenge_failed"
"body": {
{"Headers":[{"Key":"Content-Type","Value":["text/plain; charset=utf-8"]}]}
}
I think I'm missing something - is there another way to get the body of the POST-Request? I mean, I can get everything else - except the body ( or it says it is empty).
EDIT4:
I tried to read the body with another function I found - without success, returns empty string - but to let you know what I already tried, here it is:
[HttpPost]
public IHttpActionResult ReceivePost()
{
var bodyStream = new
StreamReader(HttpContext.Current.Request.InputStream);
bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
var bodyText = bodyStream.ReadToEnd();
return Json(bodyText);
}
While trying to solve this I learnt a lot - but this one seems to be so impossible, that I think I will never solve it alone. Thousands of tries with thousands of different functions - I have tried hundreds of parameters and functions in all of WebApi / ASP.NET / MVC / whatever - why is there no BODY? Does it exist? What's his/her name? Where does it live? I really wanna hang out with that parameter if I ever find it, must be hidden at the end of the rainbow under a pot of gold.
If you can use ASP.NET Core 2, this will do the trick:
public async Task<ActionResult> HandleEvent([FromBody] dynamic data)
=> new ContentResult {Content = data.challenge};
According to the official documentation linked to in the OP you have to format your response depending on the content type you return.
It is possible you are not returning the value (challenge) in one of the expected formats.
Once you receive the event, respond in plaintext with the challenge
attribute value. In this example, that might be:
HTTP 200 OK
Content-type: text/plain
3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P
To do the above you would have needed to return your request differently
[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
//Please verify that the token value found in the payload
//matches your application's configured Slack token.
if (ModelState.IsValid && json != null && ValidToken(json.token)) {
var response = Request.CreateResponse(HttpStatusCode.OK, json.challenge, "text/plain");
return ResponseMessage(response);
}
return BadRequest();
}
Documentation also shows
Or even JSON:
HTTP 200 OK
Content-type: application/json
{"challenge":"3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}
Which again would have to be formatted a little differently
[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
//Please verify that the token value found in the payload
//matches your application's configured Slack token.
if (ModelState.IsValid && json != null && ValidToken(json.token)) {
var model = new { challenge = json.challenge };
return Ok(model);
}
return BadRequest();
}
Here's how you can access the data:
[HttpPost]
[Route("something")]
public JsonResult DoSomething()
{
var token = HttpContext.Request.Form["token"];
// Is the same as:
// var token = Request.Form["token"];
return new JsonResult(token);
}
I suggest using a Request Bin for further debugging.
We have a fun situation where we are storing json as a string in SQL Server. We don't not care what is in this object its pretty much a passthrough property. Passthrough meaning we just save it for clients and return it as is. We never read it in C#. I'm storing it as a nvarchar in the database but I'm trying to figure out how i can automagically serialize that string into a json object to return to the client. I dont want to have to in javascript call fromJson.
We are using Newtonsoft as our Json Serializer. Here is the highlevel setup:
DTO:
public class MyDto{
public dynamic SessionBag { get;set;}
}
Entity Framework Entity:
public class My{
public string SessionBag { get;set;}
}
A client would post/put us:
{"SessionBag":{"Name":"test"}}
We would then save it in the db as a string:
"{"Name":"test"}"
How can I serialize this so when it returns from Web.API it looks like:
{
SessionBag:{
Name: "test"
}
}
I'm currently messing around trying to get it to save using dynamic / object. But i can't figure how how to return it as a json object. I would love to figure out how to do this with just annotations.
Here is how I convert it to a string to save:
if (dto.SessionBag != null){
var serializer = JsonSerializer.Create(new JsonSerializerSettings(){
NullValueHandling = NullValueHandling.Ignore
});
using (var writer = new StringWriter()){
serializer.Serialize(writer, dto.SessionBag);
entity.SessionData = writer.ToString();
}
}
In case its helpful our WebApiControllers are pretty simple and just return an IHttpActionResult with the dto. All feedback is welcome.
So I think i figured it out. In my dto:
[JsonIgnore]
public string SessionBagString { get; set; }
public JObject SessionBag
{
get
{
if (!string.IsNullOrEmpty(SessionBagString))
{
return JObject.Parse(SessionBagString);
}
return null;
}
set
{
if(value != null)
{
SessionBagString = value.ToString();
}
}
}
In my repo code I now have:
if (dto.SessionBag != null)
{
entity.SessionBagString = dto.SessionBagString;
}
That pretty much worked for me. Let me know if there is a better way to do it.
I'm sending a request to server in the following form:
http://localhost:12345/api/controller/par1/par2
The request is correctly resolved to a method like:
[HttpPost]
public void object Post(string par1, string par2)
However, I pass additional data through the request content. How can I retrieve these data?
For the sake of example, let's say, that the request is sent from the form:
<form action="http://localhost:12345/api/controller/par1/par2" method="post">
<input type="hidden" name="data" value="value" />
<input type="submit" name="submit" value="Submit" />
</form>
From answer in this question:
How to get Json Post Values with asp.net webapi
Autoparse using parameter binding; note that the dynamic is made up of JToken, hence the .Value accessor.
public void Post([FromBody]dynamic value) {
var x = value.var1.Value; // JToken
}
Read just like Request.RequestUri.ParseQueryString()[key]
public async Task Post() {
dynamic obj = await Request.Content.ReadAsAsync<JObject>();
var y = obj.var1;
}
Same as #2, just not asynchronously (?) so you can use it in a helper method
private T GetPostParam<T>(string key) {
var p = Request.Content.ReadAsAsync<JObject>();
return (T)Convert.ChangeType(p.Result[key], typeof(T)); // example conversion, could be null...
}
Caveat -- expects media-type application/json in order to trigger JsonMediaTypeFormatter handling.
After spending a good bit of time today trying to wrap my brain around the (significant but powerful) paradigm shift between old ways of processing web form data and how it is done with WebAPI, I thought I'd add my 2 cents to this discussion.
What I wanted to do (which is pretty common for web form processing of a POST) is to be able to grab any of the form values I want, in any order. Say like you can do if you have your data in a System.Collections.Specialized.NameValueCollection. But turns out, in WebAPI, the data from a POST comes back at you as a stream. So you can't directly do that.
But there is a cool little class named FormDataCollection (in System.Net.Http.Formatting) and what it will let you do is iterate through your collection once.
So I wrote a simple utility method that will run through the FormDataCollection once and stick all the values into a NameValueCollection. Once this is done, you can jump all around the data to your hearts content.
So in my ApiController derived class, I have a post method like this:
public void Post(FormDataCollection formData)
{
NameValueCollection valueMap = WebAPIUtils.Convert(formData);
... my code that uses the data in the NameValueCollection
}
The Convert method in my static WebAPIUtils class looks like this:
/// <summary>
/// Copy the values contained in the given FormDataCollection into
/// a NameValueCollection instance.
/// </summary>
/// <param name="formDataCollection">The FormDataCollection instance. (required, but can be empty)</param>
/// <returns>The NameValueCollection. Never returned null, but may be empty.</returns>
public static NameValueCollection Convert(FormDataCollection formDataCollection)
{
Validate.IsNotNull("formDataCollection", formDataCollection);
IEnumerator<KeyValuePair<string, string>> pairs = formDataCollection.GetEnumerator();
NameValueCollection collection = new NameValueCollection();
while (pairs.MoveNext())
{
KeyValuePair<string, string> pair = pairs.Current;
collection.Add(pair.Key, pair.Value);
}
return collection;
}
Hope this helps!
I had a problem with sending a request with multiple parameters.
I've solved it by sending a class, with the old parameters as properties.
<form action="http://localhost:12345/api/controller/method" method="post">
<input type="hidden" name="name1" value="value1" />
<input type="hidden" name="name2" value="value2" />
<input type="submit" name="submit" value="Submit" />
</form>
Model class:
public class Model {
public string Name1 { get; set; }
public string Name2 { get; set; }
}
Controller:
public void method(Model m) {
string name = m.Name1;
}
It is hard to handle multiple parameters on the action directly. The better way to do it is to create a view model class. Then you have a single parameter but the parameter contains multiple data properties.
public class MyParameters
{
public string a { get; set; }
public string b { get; set; }
}
public MyController : ApiController
{
public HttpResponseMessage Get([FromUri] MyParameters parameters) { ... }
}
Then you go to:
http://localhost:12345/api/MyController?a=par1&b=par2
Reference: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
If you want to use "/par1/par2", you can register an asp routing rule. eg routeTemplate: "API/{controller}/{action}/{a}/{b}".
See http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
Try this.
public string Post(FormDataCollection form) {
string par1 = form.Get("par1");
// ...
}
It works for me with webapi 2
None of the answers here worked for me. Using FormDataCollection in the post method seems like the right answer but something about my post request was causing webapi to choke. eventually I made it work by including no parameters in the method call and just manually parsing out the form parameters like this.
public HttpResponseMessage FileUpload() {
System.Web.HttpRequest httpRequest = System.Web.HttpContext.Current.Request;
System.Collections.Specialized.NameValueCollection formData = httpRequest.Form;
int ID = Convert.ToInt32(formData["ID"]);
etc
I found for my use case this was much more useful, hopefully it helps someone else that spent time on this answer applying it
public IDictionary<string, object> GetBodyPropsList()
{
var contentType = Request.Content.Headers.ContentType.MediaType;
var requestParams = Request.Content.ReadAsStringAsync().Result;
if (contentType == "application/json")
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(requestParams);
}
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
Is there a way to handle form post data in a Web Api controller?
The normal approach in ASP.NET Web API is to represent the form as a model so the media type formatter deserializes it. Alternative is to define the actions's parameter as NameValueCollection:
public void Post(NameValueCollection formData)
{
var value = formData["key"];
}
ON WEB API.
[HttpGet]
[Route("api/Get_EXCUTA_PROCEDURE_IBESVNDACMVDD")]
public IHttpActionResult Get(int CodigoPuxada...)
{
string retornoErro = string.Empty;
try
{
//int codigoPuxada = entrada.CodigoPuxada;
SetKeyAtual(CodigoPuxada);
var repo = new ItemBroker_Dim_Canal_BookRepositorio(ConnectionString);
try
{
var dadosRetorno = repo.ExcuteProcedure_Busca_vbc_(CodigoPuxada,...); // method return object (dataset)
return Ok(dadosRetorno);
}
catch
{
throw;
}
}
catch (Exception ex)
{
retornoErro = ex.Message;
if (ex.InnerException != null)
retornoErro = ex.InnerException.ToString();
}
return Ok(retornoErro);
}
Other projet invoke web api...
(USING RESTSHARP DLL)
RestClient clientHttpPost1 = null;
string dadosVbc123 = string.empty;
clientHttpPost1 = new RestSharp.RestClient($"{urlWebApiAvante}Get_EXCUTA_PROCEDURE_IBESVNDACMVDD?CodigoPuxada=...");
RestSharp.RestRequest request2 = new RestSharp.RestRequest(RestSharp.Method.GET);
request2.RequestFormat = RestSharp.DataFormat.Json;
request2.AddHeader("Content-Type", "application/json;charset=utf-8");
string strAux1 = string.Empty;
request2.Timeout = 180000;
RestSharp.IRestResponse response = clientHttpPost1.Execute(request2);
if ((response != null) && response.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
var dataObjects = response.Content.ToString().Trim();
dadosVbc123 = dataObjects.ToString().Replace("\t", "");
if (dadosVbc123.Trim() == "{\"IBESVNDACMVDD\":[]}")
dadosVbc123 = string.Empty;
}
...
}
// converting JSON to dataset
string val1 = dadosVbc123.Replace("{\"IBESVNDACMVDD\":", "").Replace("}]}", "}]");
DataTable dtVBC123 = (DataTable)Newtonsoft.Json.JsonConvert.DeserializeObject(val1, (typeof(DataTable)));
i'm making a request do a asp.net webapi Post Method, and i'm not beeing able to get a request variable.
Request
jQuery.ajax({ url: sURL, type: 'POST', data: {var1:"mytext"}, async: false, dataType: 'json', contentType: 'application/x-www-form-urlencoded; charset=UTF-8' })
.done(function (data) {
...
});
WEB API Fnx
[AcceptVerbs("POST")]
[ActionName("myActionName")]
public void DoSomeStuff([FromBody]dynamic value)
{
//first way
var x = value.var1;
//Second way
var y = Request("var1");
}
i Cannot obtain the var1 content in both ways... (unless i create a class for that)
how should i do that?
First way:
public void Post([FromBody]dynamic value)
{
var x = value.var1.Value; // JToken
}
Note that value.Property actually returns a JToken instance so to get it's value you need to call value.Property.Value.
Second way:
public async Task Post()
{
dynamic obj = await Request.Content.ReadAsAsync<JObject>();
var y = obj.var1;
}
Both of the above work using Fiddler. If the first option isn't working for you, try setting the content type to application/json to ensure that the JsonMediaTypeFormatter is used to deserialize the content.
After banging my head around for a while on this and trying many different things I ended up putting some breakpoints on the API server and found the key value pairs stuffed down in the request. After I knew where they were, it was easy to access them. However, I have only found this method to work with WebClient.UploadString. However, it does work easily enough and allows you to load up as many parameters as you like and very easily access them server side. Note that I am targeting .net 4.5.
CLIENT SIDE
// Client request to POST the parameters and capture the response
public string webClientPostQuery(string user, string pass, string controller)
{
string response = "";
string parameters = "u=" + user + "&p=" + pass; // Add all parameters here.
// POST parameters could also easily be passed as a string through the method.
Uri uri = new Uri("http://localhost:50000/api/" + controller);
// This was written to work for many authorized controllers.
using (WebClient wc = new WebClient())
{
try
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
response = wc.UploadString(uri, login);
}
catch (WebException myexp)
{
// Do something with this exception.
// I wrote a specific error handler that runs on the response elsewhere so,
// I just swallow it, not best practice, but I didn't think of a better way
}
}
return response;
}
SERVER SIDE
// In the Controller method which handles the POST request, call this helper:
string someKeyValue = getFormKeyValue("someKey");
// This value can now be used anywhere in the Controller.
// Do note that it could be blank or whitespace.
// This method just gets the first value that matches the key.
// Most key's you are sending only have one value. This checks that assumption.
// More logic could be added to deal with multiple values easily enough.
public string getFormKeyValue(string key)
{
string[] values;
string value = "";
try
{
values = HttpContext.Current.Request.Form.GetValues(key);
if (values.Length >= 1)
value = values[0];
}
catch (Exception exp) { /* do something with this */ }
return value;
}
For more info on how to handle multi-value Request.Form Key/Value pairs, see:
http://msdn.microsoft.com/en-us/library/6c3yckfw(v=vs.110).aspx
I searched all morning to find an answer that depicted both client and server code, then finally figured it out.
Brief intro - The UI is an MVC 4.5 project that implements a standard view. The server side is an MVC 4.5 WebApi. The objective was to POST the model as JSON and subsequently update a database. It was my responsibility to code both the UI and backend. Below is the code. This worked for me.
Model
public class Team
{
public int Ident { get; set; }
public string Tricode { get; set; }
public string TeamName { get; set; }
public string DisplayName { get; set; }
public string Division { get; set; }
public string LogoPath { get; set; }
}
Client Side (UI Controller)
private string UpdateTeam(Team team)
{
dynamic json = JsonConvert.SerializeObject(team);
string uri = #"http://localhost/MyWebApi/api/PlayerChart/PostUpdateTeam";
try
{
WebRequest request = WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
WebResponse response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
catch (Exception e)
{
msg = e.Message;
}
}
Server Side (WebApi Controller)
[Route("api/PlayerChart/PostUpdateTeam")]
[HttpPost]
public string PostUpdateTeam(HttpRequestMessage context)
{
var contentResult = context.Content.ReadAsStringAsync();
string result = contentResult.Result;
Team team = JsonConvert.DeserializeObject<Team>(result);
//(proceed and update database)
}
WebApiConfig (route)
config.Routes.MapHttpRoute(
name: "PostUpdateTeam",
routeTemplate: "api/PlayerChart/PostUpdateTeam/{context}",
defaults: new { context = RouteParameter.Optional }
);
Try this.
public string Post(FormDataCollection form) {
string par1 = form.Get("par1");
// ...
}
try using following way
[AcceptVerbs("POST")]
[ActionName("myActionName")]
public static void DoSomeStuff(var value)
{
//first way
var x = value;
}