Making a Web API method accept an xml - asp.net-web-api

I am new to Web API so if this question sounds trivial or stupid please still give a solution.
I have a requirement where the consumer of my web api wants to post an xml.
I created an empty Web API controller and added a method like so:
public class StudentController : ApiController
{
[HttpPost]
public Student GetStudent(Student studentXml)
{
Student student = new Student() { Id = 502, Course = "Chemistry" };
return student;
}
}
The param is of type Student which is the class that has the same properties as the tags in the xml.
The XML that will be posted is like so:
<StudentStatus>
<AccountID>1231</AccountID>
<Password>2132132</Password>
<Batch/>
<Sequence/>
<Test>0</Test>
<Date>09/25/2014 09:18:24</Date>
<TestNumber>1972</TestNumber>
<StatusCode>3</StatusCode>
<ID>502</ID>
</StudentStatus>
The method is suppose to return an XML in response.
That's easy with the
Accept: application/xml
But how do I make the method accept an XML?
Any help is greatly appreciated.
Regards.

Try this in the controller code...Remove Get Prefix, no need to add [HttpPost]
Put a breakpint to see if it hits there.
public void PostStudent(string studentXml)
{
//Write your logic here
}
Try this in the code from where you are posting data
using (var client = new WebClient())
{
var data = "XML data" //Try HTML.Encode if it does not work
var result = client.UploadString("http://localhost:52996/api/Student", "POST", data);
//Do something with result
}

Related

Execute a simple call to a WebAPI Get using RestRequest and a single string parameter

I have the following code in my receiving controller:
[Route("api/StudentUserId/{string}"), HttpGet]
public StudentDto StudentUserId(string userId)
{
StudentModel sm = new StudentModel(userId);
StudentDto dto = sm.ConvertToDto();
return dto;
}
After running this project, I have another project that I use to test the WebAPI controller calls. I use the following code to read a student record form the database using their userId:
protected T SendRequestToReadItemUsingString<T>(string resource, string userId) where T : new()
{
string resourceString = string.Format("{0}/{{userId}}", resource);
RestRequest request = new RestRequest(resourceString, Method.GET);
request.AddUrlSegment("userId", userId);
RestClient restClient = new RestClient(Service.Location);
var response = restClient.Execute<T>(request);
T retVal = response.Data;
return retVal;
}
Comparible code seems to work if I change the userId to an int Id in both the controller and calling code. I can't seem to get it to work with string. If I place a breakpoint in the controller code it never hits it and the calling code just returns a null.
Thanks for your help
Please note that WebApi works based on reflection this means that your curly braces {vars} must match the same name in your methods.
Therefore to match this api/StudentUserId/{string} your method needs to be declare like this:
[Route("api/StudentUserId/{userId}"), HttpGet]
public StudentDto StudentUserId(string userId)
return userId;
}
Where the parameter {string} was replaced by userId.
If you want to read more about this Routing Rules here is similar post on this;
WebApi Routing Configuration

Post Binary array to Web API Controller

I am trying to POST form data which consists of few string variable and binary array.
Below is the Model for the form data.
public class FileModel
{
public string Path { get; set; }
public byte[] File { get; set; }
}
Below is my Web API Controller.
[Route("")]
public IHttpActionResult Post([FromBody]FileModel media)
{
// Can I use ??
byte[] requestFile = media.File;
string requestFilePath = media.Path;
//Process the above variables
return Ok();
}
I would like to know Can I use the following code to de-serialize the following code snippet to to read the values from the JSON payload including the binary data?
byte[] requestFile = media.File;
string requestFilePath = media.Path;
If Yes, Do I need to define any formatter class to get it working?
I normally use POSTMAN to test my RESTful endpoints.
Is it possible to use POSTMAN still to POST binary array? May be not need to write my own client
You'll need to use a serializer to serialize complex objects (multiple fields) as content for a Http Request.
For your code snippet to read the object from the content you can use this:
var requestContent = Request.Content.ReadAsAsync<FileModel>(GetJsonSerializer()).Result;
Here's the serializer boilerplate code.
private JsonMediaTypeFormatter GetJsonSerializer()
{
JsonSerializerSettings settings = new JsonSerializerSettings()
{
PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All,
TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
};
return new JsonMediaTypeFormatter() { SerializerSettings = settings };
}
I'm not sure how to use POSTMAN to test this. A simple .net client would be:
var Client = new HttpClient();
Client.BaseAddress = new Uri("localhost"); //whatever your endpoint is
FileModel objectToSend = new FileModel();
var objectContent = new ObjectContent<FileModel>(objectToSend, GetJsonSerializer() );
var response = Client.PostAsync("uri", objectContent);
You are able to use POSTMAN to test binary file input. Selecting the body tab, you can then pick the radio button "binary" and then choose file.

How do you read POST data in an ASP.Net MVC 3 Web API 2.1 controller?

This does not seem to be as easy as I thought. I found some solutions on the web, but they are not working for me. I have an ASP.Net MVC 3 project with the Microsoft ASP.Net Web API 2.1 nuget package installed. Now, I want to be able to read data posted to a web api controller. The data sent will vary, so I cannot used a strongly typed ViewModel.
Here are the solutions I tried:
public void Post([FromBody]string value)
{
...
}
public void Post([FromBody]List<string> values)
{
...
}
public void Post([FromBody]NameValueCollection values)
{
...
}
But my value or values variables are always empty. I know the controller is receiving data however because I can check it by accessing (System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"].Request.Form. It does not look like the proper way to retrieve the data though. There ought to be a cleaner way.
UPDATE:
Here is how I am posting the information:
I am posting the data from another controller in the same web application:
public ActionResult SendEmailUsingService()
{
dynamic email = new ExpandoObject();
email.ViewName = "EmailTest";
email.From = "fromaddress#yahoo.com";
email.To = "toaddress#gmail.com";
email.Fullname = "John Smith";
email.Url = "www.mysite.com";
IDictionary<string, object> data = email;
using (var wb = new WebClient())
{
string url = BaseUrlNoTrailingSlash + Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Emailer" });
var response = wb.UploadValues(url, "POST", data.ToNameValueCollection());
}
return View();
}
And here is what I am getting in my Post web api controller if I declare an httpContext variable like this:
var httpContext = (System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"];
httpContext.Request.Form =
{ViewName=EmailTest&From=fromaddress%40yahoo.com&To=toaddress%40gmail.com&Fullname=John+Smith&Url=www.mysite.com}
httpContext.Request.Form is a System.Collections.Specialized.NameValueCollection {System.Web.HttpValueCollection}
I finally found the answer to my question here:
Web API Form Data Collection
The solution is to use FormDataCollection:
public void Post([FromBody]FormDataCollection formData)
{
...
}

How To Pass formdata parameters into ASP.NET WebAPI without creating a record structure

I have data coming into my form that looks like the image below (sessionsId: 1367,1368).
I've create c# in my webapi controller that works as below. when I've tried ot just make use SessionIds as the parameter (or sessionIds) by saying something like PostChargeForSessions(string SessionIds) either null gets passed in or I get a 404.
What is the proper way to catch a form parameter like in my request without declaring a structure.
(the code below works, but I'm not happy with it)
public class ChargeForSessionRec
{
public string SessionIds { get; set; }
}
[HttpPost]
[ActionName("ChargeForSessions")]
public HttpResponseMessage PostChargeForSessions(ChargeForSessionRec rec)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, new ShirtSizeReturn()
{
Success = true,
//Data = shirtSizeRecs
});
return response;
}
You can declare the action method like this.
public HttpResponseMessage Post(string[] sessionIds) { }
If you don't want to define a class, the above code is the way to go. Having said that, the above code will not work with the request body you have. It must be like this.
=1381&=1380

Post Scalar data type using HttpClient.PostAsJsonAsync

I am invoking ASP .Net Web API using HttpClient and invoke actions successfully. Also I am able to POST custom object into action as well.
Now problem I am facing is, not able to post scalar data type like Integer,String etc...
Below is my controller and application code that invokes action
// Test application that invoke
[Test]
public void RemoveCategory()
{
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = client.PostAsJsonAsync<string>("http://localhost:49931/api/Supplier/RemoveCategory/", "9").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
// Controller and Action in Web API
public class SupplierController : ApiController
{
NorthwindEntities context = new NorthwindEntities();
[HttpPost]
public HttpResponseMessage RemoveCategory(string CategoryID)
{
try
{
int CatId= Convert.ToInt32(CategoryID);
var category = context.Categories.Where(c => c.CategoryID == CatId).FirstOrDefault();
if (category != null)
{
context.Categories.DeleteObject(category);
context.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, "Delete successfully CategoryID = " + CategoryID);
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Invalid CategoryID");
}
}
catch (Exception _Exception)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, _Exception.Message);
}
}
When I Post custome object that represent "Category" table in Northwind database all things working properly but I am not able to post scalar data like Integer and String
When I am post string data type I am getting following exception
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:49931/api/Supplier/RemoveCategory/'.","MessageDetail":"No action was found on the controller 'Supplier' that matches the request."}
Can anyone guide me?
You will have to mark your CategoryID parameter as [FromBody]:
[HttpPost]
public HttpResponseMessage RemoveCategory([FromBody] string CategoryID)
{ ... }
By default, simple types such as string will be model bound from the URI.

Resources