2

I have a PUT request which is returning a 404 error from my client, the code looks like this:

    {
        string uriupdatestudent = string.Format("http://localhost:8000/Service/Student/{0}/{1}/{2}", textBox16.Text, textBox17.Text, textBox18.Text);
        byte[] arr = Encoding.UTF8.GetBytes(uriupdatestudent);
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uriupdatestudent);
        req.Method = "PUT";
        req.ContentType = "application/xml";
        req.ContentLength = arr.Length;
        using (Stream reqStrm = req.GetRequestStream())
        {
            reqStrm.Write(arr, 0, arr.Length);
            reqStrm.Close();
        }
        using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
        {
            MessageBox.Show(resp.StatusDescription);
            resp.Close();
        }
    }

The OperationContract and Service looks like this:

    [OperationContract]
    [WebInvoke(Method = "PUT", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Student")]
    void UpdateStudent(Student student);

    public void UpdateStudent(Student student) 
    {
        var findStudent = students.Where(s => s.StudentID == student.StudentID).FirstOrDefault();

        if (findStudent != null)
        {
            findStudent.FirstName = student.FirstName;
            findStudent.LastName = student.LastName;
        }

    }
[DataContract(Name="Student")]
public class Student
{
    [DataMember(Name = "StudentID")]
    public string StudentID { get; set; }
    [DataMember(Name = "FirstName")]
    public string FirstName { get; set; }
    [DataMember(Name = "LastName")]
    public string LastName { get; set; }
    [DataMember(Name = "TimeAdded")]
    public DateTime TimeAdded;
    public string TimeAddedString
James A Mohler
  • 11,060
  • 15
  • 46
  • 72
Kirsty White
  • 1,210
  • 3
  • 26
  • 54

2 Answers2

1

So in order to answer my question I had to do two things:

I had to change my operation contract so that it can take the input string studentID, then I could delcare the student collection.

    [OperationContract]
    [WebInvoke(Method = "PUT", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Student/{studentID}")]
    void UpdateStudent(string studentID, Student student);

    public void UpdateStudent(string studentID, Student student) 
    {
        var findStudent = students.Where(s => s.StudentID == studentID).FirstOrDefault();

        if (findStudent != null)
        {
            findStudent.FirstName = student.FirstName;
            findStudent.LastName = student.LastName;
        }

    }

Then from the client side I had to go back to using the string builder method in order to send the collection as xml.

    {
        string uriupdatestudent = string.Format("http://localhost:8000/Service/Student/{0}", textBox16.Text);
        StringBuilder sb = new StringBuilder();
        sb.Append("<Student>");
        sb.AppendLine("<FirstName>" + this.textBox17.Text + "</FirstName>");
        sb.AppendLine("<LastName>" + this.textBox18.Text + "</LastName>");
        sb.AppendLine("</Student>");
        string NewStudent = sb.ToString();
        byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uriupdatestudent);
        req.Method = "PUT";
        req.ContentType = "application/xml";
        req.ContentLength = arr.Length;
        Stream reqStrm = req.GetRequestStream();
        reqStrm.Write(arr, 0, arr.Length);
        reqStrm.Close();
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        MessageBox.Show(resp.StatusDescription);
        reqStrm.Close();
        resp.Close();
    }

There was a person who had put an answer prior to this and he was correct so I would like to thank you and your answer would have been accepted! (if it wasnt deleted)

Kirsty White
  • 1,210
  • 3
  • 26
  • 54
  • 2
    glad that worked for you, my earlier answer's below. I thought it wasn't working for you due to the downvotes so I deleted it. Good to hear that you got it working – KodeKreachor Apr 15 '12 at 04:03
0

Based on the uri you're calling, is your service able to resolve it given the extra routing information being passed to it?

You could try updating the service method signature to accept and map the ncoming uri parameters:

[WebInvoke(Method = "PUT", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Student/{fname}/{lname}/{id}")]
    void UpdateStudent(string fname, string lname, string id);

Otherwise you could just serialize your Student object on the client into XML and send it along with the request inside the body of the request. In this case you would simply make a request to: http://localhost:8000/Service/Student and WCF would deserialize the incoming request's body to a corresponding Student object.

KodeKreachor
  • 8,852
  • 10
  • 47
  • 64
  • What would you then do in the UpdateStudent? If I use a string I cant achieve this `findStudent.FirstName = student.FirstName;` – Kirsty White Apr 14 '12 at 19:44
  • In my first suggestion, the first name, last name, and id would all come in as separate string parameters to your service method, so you could then use them as you normally would any other method parameter. My second suggestion would actually deserialize the request's body into your Student object and you could then use it just as you are. – KodeKreachor Apr 14 '12 at 19:55
  • If your service is implementing a specific interface then you'd have to update the UpdateStudent method signature in the interface to use the separate string parameters instead of the Student object. If you don't want to change your service interface then my first suggestion won't work for you, you'd have to use my second suggestion. – KodeKreachor Apr 14 '12 at 20:10
  • 1
    sorry I totlly missed this I always forget about the inbox lol – Kirsty White Apr 17 '12 at 22:22