Calling restful wcf web service bad request - c#

My restful wcf web service is written in Visual Studio 2010.
This is the code in Service1.svc.cs
namespace ContactRegistration
{
public class Service1 : IService1
{
public string JSONDataPost(Contact ContactObject)
{
//code to put the data in the database goes here
//we'll pretend it all went okay and return
return "0|Data added okay";
}
}
}
This is the code in IService1.cs
namespace ContactRegistration
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "/JSONDataPost",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string JSONDataPost(Contact ContactObject);
}
[DataContract]
public class Contact
{
[DataMember]
public string Organisation { get; set; }
[DataMember]
public string FirstName { get; set; }
public Contact(string organisation, string firstName)
{
this.Organisation = organisation;
this.FirstName = firstName;
}
}
}
Here is the web config.
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="ContactRegistration.Service1Behavior"
name="ContactRegistration.Service1">
<endpoint address="" binding="webHttpBinding"
contract="ContactRegistration.IService1" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ContactRegistration.Service1Behavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
When I call the web service from a web application the URI I am using is:
Uri address = new Uri("http://www.myserver/ContactRegistration/Service1.svc/JSONDataPost");
And I am getting a bad request 400 back from the server.
Is the [OperationContract] written correctly? Is there something wrong with the URITemplate? I have looked at dozens of examples today and they seem to have the URITemplate as '/NameOfMethod' which is what I have done.
EDIT: Bit of code to show the beginning of how it is called
Uri address = new Uri("http://www.myserver/ContactRegistration/Service1.svc/JSONDataPost");
// Create the web request
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
// Set type to POST
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
// Create the data we want to send
Contact myContact = new Contact();
myContact.Organisation = "Society of Fruit Flies";
myContact.FirstName = "Fred";

Related

Not Getting the Data in URL by Web Service

I am making web service and not getting the parse data through URL
Code of WEB SERVICE is this. my IService class
namespace DataService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedResponse)]
List<RequestData> GetUser(RequestData data);
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "UsersList/{id}", RequestFormat = WebMessageFormat.Json)]
RequestData UsersList(string id);
}
[DataContract]
public class RequestData
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Address { get; set; }
}
}
this is my service1 class inherited by Iservice1 Class
namespace DataService
{
public class Service1 : IService1
{
public List<RequestData> GetUser(RequestData data)
{
List<RequestData> list = new List<RequestData>();
if (data.Name.ToUpper() == "MAIRAJ")
{
list.Add(new RequestData
{
Name = "Mairaj",
Age = 25,
Address = "Test Address"
});
list.Add(new RequestData
{
Name = "Ahmad",
Age = 25,
Address = "Test Address"
});
list.Add(new RequestData
{
Name = "Minhas",
Age = 25,
Address = "Test Address"
});
}
return list;
}
public RequestData UsersList(string userId)
{
if (userId == "1")
{
return new RequestData
{
Name = "Mairaj",
Age = 25,
Address = "Test Address"
};
}
else
{
return new RequestData
{
Name = "Amir",
Age = 25,
Address = "Test Address"
};
}
}
}
}
I am giving this URL after deploying web service http://116.58.61.180/ADG/Service1.svc
what Exact url should parse to get the data
this is my web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I think you just forgot few things in your web.config :
<endpointBehaviors>
<behavior>
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
And
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
If you don't put all this stuffs in your web.config you won't be able to get your services working.
The full Web.config would be like this :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
For more details I had written few months ago a post on my blog about WCF and REST :
Simple WCF and REST service
WCF and POST method
Follow these steps:
Decorate your service class with follwing attribute
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
Web.config should look like this
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
Your Global.asax should look like this.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
// Edit the base address of Service1 by replacing the "Service1" string below
RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
}
}

WebInvoke with Complex Type parameter does not work for Json endpoint

I want to create WCF Restful service that takes Complex Type as a parameter in Json format and return Json. I read a lots of article and examine many samples on the web. Some article suggest to add tag in Endpoint behavior and decorate Service method as below,
[WebInvoke(UriTemplate = "/PlaceOrder",
RequestFormat= WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "POST")]
In this case, WCF returns "Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'." error message.
Another suggested way(as in this article http://dotnetmentors.com/wcf/wcf-rest-service-to-get-or-post-json-data-and-retrieve-json-data-with-datacontract.aspx) is add "" tag to Endpoint behavior instead of . But in this case IIS returns ("The remote server returned an error: (400) Bad Request.") error message.
Can you please help me how to create Restful Service that takes complex type argument in json format and return json.
This works:
[ServiceContract]
public interface IService
{
[WebInvoke(Method = "POST", UriTemplate = "/ModifyCustomer", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Customer ModifyCustomer(Customer customer);
}
public class Service : IService
{
public Customer ModifyCustomer(Customer customer)
{
customer.Age += 1;
return customer;
}
}
public class Customer
{
public string Name { get; set; }
public int Age { get; set; }
}
And self-hosting like:
var webServiceHost = new WebServiceHost(typeof(Service),
new Uri("http://localhost:12345"));
webServiceHost.AddServiceEndpoint(typeof(IService), new WebHttpBinding(),"");
webServiceHost.Open();
In Postman:
And in IIS Express with the following config:
<system.serviceModel>
<services>
<service name="RestServiceTest.Service" behaviorConfiguration="myServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="RestServiceTest.IService" behaviorConfiguration="myEndpointBehavior">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="myEndpointBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Result from postman:

500 Interval Server Error while accessing WCF service from http and Google Chrome Extension Simple REST Client

THis is the service which I created for Android device to post data but this service doesn't work for me. I called this service through an Android but nothing happens just received an error message of -500 in LogCat. I also check this service on HTTP and SIMPLE REST Client (Google Chrome Extension) but received an error message. Error message is given below. and this service is also published on IIS.
Error Message
The message with Action '' cannot be processed at the receiver,due to a ContractFilter mismatch at the EndpointDispatcher.
This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.
Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)
These are the params which im passing to the service:
{"mycar":{"Name":"a","Make":"gfgfd ","Model":"web "}}
and here is the service source code
namespace CarSercive
{
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class Service1 : IService1
{
// myCar test = new myCar();
public void UpdateMyCar(myCar mycar) {
string strConnectionString = ConfigurationManager.ConnectionStrings["Database1"].ConnectionString;
SqlConnection conn = new SqlConnection(strConnectionString);
conn.Open();
using (SqlCommand cmd = new SqlCommand("Insert into TestingTable (Name,Make,Model) Values (#Name,#Make,#Model)", conn)) {
cmd.Parameters.AddWithValue("#Name", mycar.Name);
cmd.Parameters.AddWithValue("#Make", mycar.Make);
cmd.Parameters.AddWithValue("#Model", mycar.Model);
int queryResult = cmd.ExecuteNonQuery();
} conn.Close();
}
}
}
web.config
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
<authentication mode="Windows"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
<system.serviceModel>
<services>
<service name="CarSercive.Service1" behaviorConfiguration="web">
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" contract="CarSercive.IService1"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="web">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
IService1.cs
namespace CarSercive
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(
Method = "POST",
UriTemplate = "MyCar",
//BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
void UpdateMyCar(myCar mycar);
}
[DataContract]
public class myCar
{
[DataMember(Name = "Name")]
public string Name
{
get;
set;
}
[DataMember(Name="Model")]
public string Model
{
get;
set;
}
[DataMember(Name="Make")]
public string Make
{
get;
set;
}
}
}
You need to add a JSON endpoint to your web.config file.
<system.serviceModel>
<domainServices>
<endpoints>
<add name="JSON" type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</endpoints>
</domainServices>
make sure to link to the assembly Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory in your project

Method Not Found in WCF service?

I am newbie in creating WCF web service. I am using VS2012 with target framework 4.5. I have added a WCF Service file in my project.
In "IService.cs" I have written the following code
namespace _3TWebServ
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
UriTemplate = "Calculate")]
String Calculate(Inputs ip1);
}
[DataContract]
public class Inputs
{
[DataMember(Name = "Coil_type")]
public string Coil_type { get; set;}
[DataMember(Name = "Finned_length")]
public string Finned_length { get; set;}
}
}
and in "Service.svc.cs"
namespace _3TWebServ
{
public class Service1 : IService1
{
[DataMember]
public string input;
public String Calculate(Inputs ip1)
{
String str = ip1.Coil_type + ip1.Finned_length;
return str;
}
}
}
But the problem comes when I run my service its not showing my method Calulate, When I pass my URL as Following
localhost:2121/Service1.svc/Calculate it shows "method not allowed" error.
I have done some Googling and enabled my IIS manager Directory Browsing. My config file is following
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="_3TWebServ.IService1" name="_3TWebServ.Service1">
<endpoint address="" behaviorConfiguration="Rest" binding="webHttpBinding" contract="_3TWebServ.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="_3TWebServ.IService1">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="Rest">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I can see a few possible issues.
Your Calculate method is set for a HTTP POST request. You should make a HTTP POST request to get proper response.
Your request format is JSON (RequestFormat attribute property value), so make sure your request body contains the parameters in JSON format ({ "Coil_type" : "type", "Finned_length": 12 }).
Why do you have the [DataMember] public string input on the service implementation? Service implementations should generally carry operation contracts.

Bad Request to RESTful WCF Service Forces IIS to Recycle App Pool

I am attempting to create and host a simple RESTful WCF Service. The service works perfectly except for 1 situation. I attempt to perform a POST to insert a new object into my static List using the JSON request of:
{"sampleItem":{"Id":1,"StartValue":2,"EndValue":3}}
If I then change the request to be:
{"sampleItemBlah":{"Id":1,"StartValue":2,"EndValue":3}}
I get a 500 response and all future POST's return a 500 error until I recycle my IIS App Pool and then it starts to work again.
It doesn't appear that the service is in a faulted state because I can still perform GET's and get data back. I turned on trace debugging and I do not see any errors in my log file.
Does anyone have any ideas?
Here is my Service Contract:
[ServiceContract]
public interface IWcfRestService
{
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
SampleItem Insert(SampleItem sampleItem);
}
[DataContract]
public class SampleItem
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int StartValue { get; set; }
[DataMember]
public int EndValue { get; set; }
}
And here is my implementation:
public class WcfRestService : IWcfRestService
{
private static readonly List<SampleItem> Items = new List<SampleItem>();
public SampleItem Insert(SampleItem sampleItem)
{
return BaseInsert(sampleItem);
}
private static SampleItem BaseInsert(SampleItem sampleItem)
{
if (Items.Exists(x => x.Id == sampleItem.Id))
Items.RemoveAll(x => x.Id == sampleItem.Id);
Items.Add(sampleItem);
return sampleItem;
}
}
And finally here is my ServiceModel section of my Web.config:
<services>
<service behaviorConfiguration="Services.ServiceBehavior"
name="WcfRestServiceApp.WcfRestService">
<endpoint address=""
behaviorConfiguration="RESTBehavior"
binding="webHttpBinding"
contract="WcfRestServiceApp.IWcfRestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RESTBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Services.ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Any and all help is greatly appreciated.
It turned out that the problem was with using the tag:
BodyStyle = WebMessageBodyStyle.Wrapped
When I removed it, the requirement to have:
{"sampleItem":{"Id":1,"StartValue":2,"EndValue":3}}
turned into:
{"Id":1,"StartValue":2,"EndValue":3}
This forced the cast to the correct object type and if the field wasn't present, it set the value to null or the type's default empty value.

Categories