2

So I have been struggling to get this work for some time now. Let me explain the requirement. I have to write a WebAPI that will accept an XML, do some look up, and return a response.

I am new to this so sought some help. The suggestion was to create a custom object that represents the incoming XML and use that object as the param for the method exposed by the WebAPI. The result will be a class that's not a problem.

Here are the steps done.

Created an empty WebAPI project. Added a class that represents the incoming XML.

Incoming XML:

<InComingStudent>
<StudentID>10</StudentID>
<Batch>56</Batch>
</InComingStudent>

The class:

public class InComingStudent
{
    public string StudentID { get; set; }
    public string Batch { get; set; }
}

Return object of this type:

public class StudentResult
{
    public string StudentID { get; set; }
    public string Batch { get; set; }
    public string Score { get; set; }
}

Added a Students controller with this method:

public class StudentsController : ApiController
{
    [HttpPost]
    public StudentResult StudentStatus(InComingStudent inComingStudent)
    {

        ProcessStudent po = new ProcessStudent();
        StudentResult studentResult = po.ProcessStudent();
        return StudentResult;
    }
}

Ran the service. It opened in a new browser with 404. That's ok as I don't have a starting page.

Wrote a console app to test:

private static async void PostToStudentService()
{
    using (var client = new HttpClient())
    {
        var studentToPost = new InComingStudent() { StudentID = "847", Batch="56"};
        client.BaseAddress = new Uri("http://localhost:53247/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

        HttpResponseMessage response = await client.PostAsXmlAsync("api/Students/StudentStatus", studentToPost);

        if (response.IsSuccessStatusCode)
        {
            // Print the response
        }
    }
}

MediaTypeWithQualityHeaderValue is set to application/xml. So far so good. When the service is running and I run the console app, the response is 404 "Not Found".

What am I missing?

Any help is greatly appreciated.

Regards.

Codehelp
  • 4,157
  • 9
  • 59
  • 96

1 Answers1

1

Have you tried the [FromBody] Attribute?

public class StudentsController : ApiController
{
    [HttpPost]
    public StudentResult StudentStatus([FromBody]InComingStudent inComingStudent)
    {
        ProcessStudent po = new ProcessStudent();
        StudentResult studentResult = po.ProcessStudent();
        return StudentResult;
    }
}

And as a suggestion, I would use Attribute-Routing.

public class StudentsController : ApiController
{
    [HttpPost, Route("api/stutents/studentsstatus")]
    public StudentResult StudentStatus([FromBody]InComingStudent inComingStudent)
    {
        // ...
   }
}
MichaelS
  • 3,809
  • 2
  • 26
  • 33
  • First of thanks for your time & help. The service hits the breakpoint but the InComingStudent comes in as null. Any clues!!! – Codehelp Oct 31 '14 at 10:09
  • Nothing just added the [FromBody] and ran the service with a bp. Ran the console app passing in the Student object. – Codehelp Oct 31 '14 at 10:13
  • Can you please use fiddler (free tool from telerik) to analyse what exactly goes over the wire? With fiddler you can see if the XML is formatted correctly and contains all Information you passed in. – MichaelS Oct 31 '14 at 10:18
  • In the Composer, set the type to POST, put the URL of the service and pasted the XML in the Request Body area. Hit execute. This time does not even hit the bp in the service. Fiddler says 415. – Codehelp Oct 31 '14 at 10:26
  • If you run your console app, can you see this request in fiddler? Is the XML in the body valid? – MichaelS Oct 31 '14 at 10:30
  • Fiddler seems to ignore local requests so I composed the same from Fiddler and set the Content-Type: text/xml. Now the bp is hit but the object is still null. Checked the XML in Inspectors tab and it shows the xml like the tree. Looks valid in there!!! – Codehelp Oct 31 '14 at 10:36
  • Since you are using `application/xml` in the console app, I would use this instead of `text/xml`. So if the HTTP-POST request is exactly how it should, then the deserialization of the XML is the problem. – MichaelS Oct 31 '14 at 10:46
  • Tried annotating the Student model with data contracts and data member attributes. No go!!! Appreciate your patience. – Codehelp Oct 31 '14 at 11:07
  • I've seen you opened another question for that issue. Maybe there is a nice solution. If not, I would use JSON. I've never ever had problems with JSON. – MichaelS Oct 31 '14 at 12:41
  • So the customer is hell bent on sending XML and the powers that be don't understand any of the technicalities. I will now go with HttpRequestMessage instead of the InComingStudent class and then use LINQ from there on. Thank you again for your help all along. I will accept your answer. I have learned quite a bit. – Codehelp Oct 31 '14 at 12:44