none
Simple WCF Data Service WebInvoke -- Can't find and getting a 404 error

    Question

  • I did a very simple WCF Data Service inside a basic Web Site. The Web Data Service is tied to a single SQL Database Table using Entity Framework.

    I am trying to figure how to add a WebInvoke so that I can use a HTTP Post to add a data record.

    I have the following code for Netduino.svc

    using System;
    using System.Collections.Generic;
    using System.Data.Services;
    using System.Data.Services.Common;
    using System.Linq;
    using System.ServiceModel.Web;
    using System.Web;
    
    namespace WCFdataservice
    {
      public class Netduino : DataService<npaEntities>
      {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
          // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
          // Examples:
          //config.SetEntitySetAccessRule("UBO_Netduino_Temp", EntitySetRights.AllRead | EntitySetRights.WriteMerge);
          config.SetEntitySetAccessRule("UBO_Netduino_Temp", EntitySetRights.All);
          // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
          config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    
        [WebInvoke(Method = "POST")]
        public string TempUpdate(string test)
        {
          return "Nice job! - " + test;
        }
      }
    }
    
    I tried to call the code with the following routine that is in a separate web application
    
    <pre>protected void Button3_Click(object sender, EventArgs e)
        {
          string URI = "http://localhost:12345/Netduino.svc/";
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:12345/Netduino.svc/TempUpdate?test='75'");
          request.Method = "POST";
          HttpWebResponse response = (HttpWebResponse)request.GetResponse();
          XDocument doc = XDocument.Load(response.GetResponseStream());
          Literal1.Text = doc.ToString();
        }
    
     
    When I tried to place the POST URL into fiddler2 I was returned this raw 
    
    <pre>HTTP/1.1 404 Not Found
    Server: ASP.NET Development Server/10.0.0.0
    Date: Sun, 27 Mar 2011 22:34:37 GMT
    X-AspNet-Version: 4.0.30319
    DataServiceVersion: 1.0;
    Content-Length: 257
    Set-Cookie: ASP.NET_SessionId=fzlaubejahz0ka55kx10ccrn; path=/; HttpOnly
    Cache-Control: private
    Content-Type: application/xml
    Connection: Close
    
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
     <code></code>
     <message xml:lang="en-CA">Resource not found for the segment 'TempUpdate'.</message>
    </error>
    
    It seems to me that the calling program can not find TempUpdate routine in Netduino.svc
    Thanks, John
    Sunday, March 27, 2011 11:34 PM

Answers

  • Hi,

    You need to allow access to the service operation (TempUpdate). This is done in a similar way as allowing access to entity sets. In your InitilaizeService call the config.SetServiceOperationAccessRule.

    In any case if you're trying to add an entity, the right way to do that is to allow write access to the entity set (unless you have very special requirements) and then simply POST the new entity to the entity set (the client WCF Data Services has direct support for this operation). Since you're using EF, all you need to do is allow write access to the entity set (as the EF provider already implements the required IUpdatable interface).

    I also noticed that you already allow the write access to the entity set (you allow All). In that case, why are you trying to add a new entity using a service operation?

    Thanks,


    Vitek Karas [MSFT]
    • Marked as answer by John.Feeney Tuesday, March 29, 2011 12:52 AM
    Monday, March 28, 2011 7:58 AM
    Moderator

All replies

  • Hi,

    You need to allow access to the service operation (TempUpdate). This is done in a similar way as allowing access to entity sets. In your InitilaizeService call the config.SetServiceOperationAccessRule.

    In any case if you're trying to add an entity, the right way to do that is to allow write access to the entity set (unless you have very special requirements) and then simply POST the new entity to the entity set (the client WCF Data Services has direct support for this operation). Since you're using EF, all you need to do is allow write access to the entity set (as the EF provider already implements the required IUpdatable interface).

    I also noticed that you already allow the write access to the entity set (you allow All). In that case, why are you trying to add a new entity using a service operation?

    Thanks,


    Vitek Karas [MSFT]
    • Marked as answer by John.Feeney Tuesday, March 29, 2011 12:52 AM
    Monday, March 28, 2011 7:58 AM
    Moderator
  • Unbelieveable....I made one change to my code (as suggested above) and it works!

    public static void InitializeService(DataServiceConfiguration config)
    
      {
    
       // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
    
       // Examples:
    
       //config.SetEntitySetAccessRule("UBO_Netduino_Temp", EntitySetRights.AllRead | EntitySetRights.WriteMerge);
    
       config.SetEntitySetAccessRule("UBO_Netduino_Temp", EntitySetRights.All);
    
       config.SetServiceOperationAccessRule("TempUpdate", ServiceOperationRights.All);
    
       config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    
    
    
      }

    Thanks for helping.

    With regards to you comment of using a client WCF Data Service....I am almost certain that I cannot do that. My client is using a simple set of the .Net Micro Framework. I know that from the code of this device I cannot add a Service Reference. That is why I can only hit my WCF Data Service from a HTTP Post or HTTP Put or HTTP Delete.

     

    john

    Tuesday, March 29, 2011 12:52 AM
  • Hi Vivek Karas,

    I am trying to do similar king of task using WCFDataServices.

    I have a Service operation Like

    [WebInvoke(Method="POST")]

    Public bool Add(string x1, string x2, string x3)

    {

    // ADDS a NEW RECORD TO DB. AND IF THE ADDITION IS SUCCESSFULL RETURs true or false

    }

    In my MVC Client Application. In the repository I have Function to Add Like

    public bool Add(string y1, string y2, string y3)

    {

    // HERE I WANT to EXECUTE THE URI AND CAPUTURE THE RETURNED VALUE. AND PASS IT TO MY CONTROLLER TO SHOW SOME ACTION IN THE VIEW.

    }

    I dont have any problem in the service. It returns the boolean value as expected. 

    I couldnt figure out how i can capture the returned boolean value in my Repository Methos.

     // OperationResponse x = dsContext.Execute(requestUri,  Microsoft.Data.OData.HttpMethod.Post);

    I tried to do something like above line.But didnt work. 

    Thanks For Your Time

    Wednesday, May 16, 2012 8:37 AM
  • Hello Vitek,

    How would the behavior of WCF Data Services (Reflection Provider ) be when the HTTP Method type is POST for the scenario mentioned by John?

    Moreover the client that I am using is NOT a .NET client, but a jQuery (ajax) API to hit the WCF Data Service. Please suggest

    Thanks

    Jegan Kunniya

    Tuesday, August 21, 2012 8:48 AM
  • Hi,

    Sorry for such a late reply (it's better to ask a new question, otherwise answered questions are usually ignored).

    To invoke a POST service operation from the client:

    With WCF Data Services Client V2 this was not possible. The only workaround was to use something like HttpWebRequest directly to issue the request and parse the response yourself.

    With WCF Data Services 5.0 (available on NuGet as well) this is now pretty easy:

    DataServiceContext.Execute<bool>(requestUri, "POST", true, <parameters if any>);

    Thanks,


    Vitek Karas [MSFT]

    Tuesday, August 21, 2012 9:09 AM
    Moderator
  • Hi Jegan,

    I must admit I don't understand the question. Could you please try to post here as many details as possible? Especially what you're trying to achieve and what you already have (if anything) and possible errors (if anything bad happens).

    Inserting an entity through POST to entity set should work just fine from jscript client. If the service is using a reflection provider, you will have to implement IUpdatable interface on your data source in order to support updates though.

    If it's about invoking a POST service operation, then should work as well from a jscript client and the server side is easier, just have a method like John has above and provide right permissions.

    Thanks,


    Vitek Karas [MSFT]

    Tuesday, August 21, 2012 9:12 AM
    Moderator