WCF POST method [duplicate] - c#

This question already has answers here:
Why does my C# client, POSTing to my WCF REST service, return (400) Bad Request?
(3 answers)
Closed 8 years ago.
{"The remote server returned an error: (405) Method Not
Allowed}System.InvalidOperationException {System.Net.WebException}
Web Config:
<service name="Service" behaviorConfiguration="RestService">
<endpoint address="web" binding="webHttpBinding"
contract="IService" behaviorConfiguration="ServiceBehavior">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="RestService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="ServiceBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<!--<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
Service :
public test TestPost(test testPost)
{
test objtest1 = new test();
objtest1.Address = "Test";
objtest1.Name = "Welcome";
return objtest1;
}
[DataContract]
public class test
{
[DataMember(Order = 0)]
public string Name { get; set; }
[DataMember(Order = 1)]
public string Address { get; set; }
}
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "TestPost/")]
test TestPost(test i);
Using Fiddler:
POST /RESTfulService/Service.svc/web/TestPost/ HTTP/1.1
User-Agent: Fiddler
Host: localhost:50458
Content-Length: 43
HTTP/1.1 400 Bad Request
Server: ASP.NET Development Server/11.0.0.0
Date: Thu, 19 Dec 2013 07:19:44 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 1647
Cache-Control: private
Content-Type: text/html
Connection: Close
GET Method is working fine, when i am trying to use POST method i am getting error

I have tried above example in my local and found that you are missing one http header called
Content-Type: application/json
Also be sure you pass right json string in request body
{"Name" : "test", "Address" : "test"}
above trick will help you to get rid of 400 bad request.

Related

Call a WCF service with a HttpClient

I have to call a WCF service. The WCF service is on and I can edit its configuration.
I want to create a client that calls the service. I cannot add the service reference to my client, so I am trying to call it with a HttpClient.
The client side code:
using (var client = new HttpClient())
{
//soapString is my input class serialized
var content = new StringContent(soapString, Encoding.UTF8, "text/xml");
using (var postResponse = client.PostAsync("http://localhost:52937/Attempts.svc/", content).Result)
{
string postResult = postResponse.Content.ReadAsStringAsync().Result;
}
}
The server side code:
[ServiceContract]
public interface IAttempts
{
[OperationContract]
void ReceiveAttemptResult(ReceiveAttemptResultInput result);
}
public class Attempts : IAttempts
{
string _backendUrl;
public void ReceiveAttemptResult(ReceiveAttemptResultInput result)
{
//...
}
}
And in the end the web.config server side:
<system.serviceModel>
<services>
<service name="it.MC.Listeners.Attempts">
<endpoint address="" contract="it.MC.Listeners.IAttempts" binding="basicHttpBinding"/>
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
When I call the service, I just obtain an empty string and I cannot stop in debug inside the service... What's wrong?
Thank you
Just in case this bedevils anyone else. Thank you #Disappointed for your missing piece of the puzzle, it prompted me to run the thing in WCF Test Client with Fiddler open to see what I was missing:
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("SOAPAction", "http://tempuri.org/IMyService/Mymethod_Async");
string soapEnvelope = "<s:Envelope xmlns:s= \"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><Mymethod_Async xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
var content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml");
HttpResponseMessage hrm = httpClient.PostAsync("http://MyService.MyDomain.com/MyService.svc", content).Result;

WCF Service not receiving data in POST

I have a WCF Service with a SOAP endpoint. I added a REST endpoint and the Get methods are working just fine. I am having trouble with a POST method which takes in an object and returns a different object. When I pass in my object, I get this error back:
"Message":"Object reference not set to an instance of an object."
Here's the code to call the service:
string URL = "http://qa.acct.webservice";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var request = new RequestGetInventory
{
BrandIDs = new string[] { "4", "42" },
AccountID = "9900003"
};
var resp = client.PostAsJsonAsync("/AxaptaService.svc/rest/GetInventory", request);
response = resp.Result;
if (response.IsSuccessStatusCode)
{
var temp = response.Content.ReadAsStringAsync().Result;
MessageBox.Show(temp); //error message received here.
}
The RequestGetInventory object is defined as follows:
[DataContract]
public class RequestGetInventory
{
[DataMember]
public string[] BrandIDs { get; set; }
[DataMember]
public string AccountID { get; set; }
}
The contract for the webservice is defined as follows:
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json)]
ResponseGetInventory GetInventory(RequestGetInventory Request);
I tried playing around with the WebInvoke parameters, but received the same error message for all viable attempts.
And this is how my web.config is set up:
<system.serviceModel>
<services>
<service behaviorConfiguration="" name="Proj.AxaptaUS.WebService.AxaptaService">
<endpoint address="rest" behaviorConfiguration="webBehavior" binding="webHttpBinding" contract="Proj.Interfaces.Axapta3.IAxaptaService"></endpoint>
<endpoint address="" binding="basicHttpBinding" contract="Proj.Interfaces.Axapta3.IAxaptaService"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="webBehavior">
<webHttp helpEnabled="true" />
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
I am not entirely sure what I'm doing wrong because I can access this using SOAP just fine. It seems like it is not getting any values for the object which I passed in, thus causing the object reference error.
Any help would be greatly appreciated! Thanks!
#jstreet posted a comment which ended up working.
I changed BodyStyle = WebMessageBodyStyle.WrappedRequest to BodyStyle = WebMessageBodyStyle.Bare and removed <enableWebScript/> from config file.
After doing those things, it started to work correctly! thanks #jstreet!

How to make a WCF Service work with https?

I am trying to enable https in my WCF service. I've added the SSL certificate to my localhost and I am able to view the WSDL when I use https in the browser. And the WCF service works fine with http without the SSL configuration in the web.config. But as soon as I change it to use https, I get the following error. If anybody can point me to the solution for this issue, it will be helpful as there isn't much reference for this error.
at Microsoft.Http.HttpStageProcessingAsyncResult.Complete(HttpStage stage, Exception e)
at Microsoft.Http.HttpStageProcessingAsyncResult.NextRequest(HttpStageProcessingAsyncResult self)
at Microsoft.Http.HttpStageProcessingAsyncResult..ctor(HttpStageProcessingAsyncState state, AsyncCallback callback, Object user)
at Microsoft.Http.HttpClient.Send(HttpRequestMessage request)
at Microsoft.Http.HttpClient.Send(HttpMethod method, Uri uri, RequestHeaders headers, HttpContent content)
at Microsoft.Http.HttpClient.Send(HttpMethod method, Uri uri)
at Microsoft.Http.HttpMethodExtensions.Method(HttpClient client, HttpMethod method, Uri uri)
at Microsoft.Http.HttpMethodExtensions.Method(HttpClient client, HttpMethod method, String uri)
at Microsoft.Http.HttpMethodExtensions.Get(HttpClient client, String uri)
at MobileScreening.Client.CommonTests.LoginPost(HttpClient client, String username, String password) in c:\TFS Projects\MobileScreening\MobileScreening.Client\CommonTests.cs:line 118
My client code where I am making the request to the service
static string LoginPost(HttpClient client, string username, string password)
{
string key = string.Empty;
try
{
var user = new UserCredentials
{
Email = username,
Password = password
};
Console.WriteLine("User Authentication:");
HttpContent content = HttpContentExtensions.CreateJsonDataContract(user);
using (HttpResponseMessage response = client.Post("AuthenticationService.svc/", content))
{
Console.WriteLine(response.Content.ReadAsString());
Console.WriteLine(response.Headers.ToString());
key = response.Headers["MobileScreening"] ?? string.Empty;
}
}
catch (Exception ex)
{
var stack = ex.StackTrace;
var innerException = ex.InnerException;
var message = ex.Message;
}
return key;
}
My interface with the operation contract
public interface IAuthenticationService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
AuthenticationWrapper Authenticate(UserCredentials user);
}
My Service to authenticate users:
public class AuthenticationService : IAuthenticationService
{
public AuthenticationWrapper Authenticate(UserCredentials user)
{
string email = user.Email ?? string.Empty;
string password = user.Password ?? string.Empty;
var authentication = new Authentication();
var authenticationWrapper = new AuthenticationWrapper();
if (!authentication.AuthenticateUser(email, password))
{
const string description = "Authentication failed. Username and/or password is incorrect.";
BLL.Authentication.ThrowAuthorisationFailed(description, email);
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
authenticationWrapper.Code = (short)HttpStatusCode.Unauthorized;
authenticationWrapper.Status = HttpStatusCode.Unauthorized.ToString();
authenticationWrapper.Message = description;
return authenticationWrapper;
}
else
{
const string description = "Authentication: Authenticate User";
LogHandler.LogMessage(email, description, Common.Event.LoginSuccessful);
string authorisationKey = authentication.CreateAuthorisationKey(email);
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.Headers.Add(Common.AuthorisationHeader, authorisationKey);
ctx.OutgoingResponse.StatusCode = HttpStatusCode.OK;
authenticationWrapper.Code = (short)HttpStatusCode.OK;
authenticationWrapper.Status = HttpStatusCode.OK.ToString();
authenticationWrapper.Message = description;
return authenticationWrapper;
}
}
}
Finally my web.config configuration for the service
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="MobileScreening.ServiceApp.AuthenticationService">
<endpoint address="AuthenticationService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IAuthenticationService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
<service name="MobileScreening.ServiceApp.ProgrammeService">
<endpoint address="ProgrammeService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IProgrammeService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
<service name="MobileScreening.ServiceApp.ActivityService">
<endpoint address="ActivityService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IActivityService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
<service name="MobileScreening.ServiceApp.UserConfigurationService">
<endpoint address="UserConfigurationService" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="MobileScreening.ServiceApp.IUserConfigurationService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="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>
</system.serviceModel>
Create a new self signed certificate using your machine name instead of the local host. Configure your solution to use the new certificate and make sure that it is installed in the client machine's under the Trusted Root Certification Authority (in your case, the client is also the server).
Also, you may also try to create the certificate pointing to the machine's fully qualified domain name.

Silverlight not sending byte array to WCF service

I have webcam in a silverlight app. I capture the image and convert it to byte array and send to WCF service. Here is the image capture code:
MessageBox.Show("about to capture");
cs.CaptureImageAsync();
cs is the camera source and is configured correctly (as is the imagecapturecompleted event). On image capture completion, this code executes:
MessageBox.Show("Image Caputred");
var img = e.Result.ToImage();
var encoder = new PngEncoder();
Stream stream = img.ToStreamByExtension("png");
byte[] file = null;
if (stream.Length > 512000)
{
img = ExtendedImage.Resize(img, 240, new NearestNeighborResizer());
stream = img.ToStreamByExtension("png");
}
if (stream.Length < 512000)
{
BinaryReader binary = new BinaryReader(stream);
file = binary.ReadBytes((int)stream.Length);
MessageBox.Show("Stream read into file with length: " + file.Length);
}
else
{
MessageBox.Show("file size too large");
}
MessageBox.Show("Process done");
cs.Stop();
label1.Content = "and answer is : " + file!= null ? file.Length.ToString() : "ERROR";
ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
ServiceReference1.ITEM i = new ServiceReference1.ITEM { Image = file };
obj.DoWorkCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(obj_DoWorkCompleted);
obj.DoWorkAsync(i);
This is my web.config in the asp.net project that configures the service:
<system.serviceModel>
<services>
<service name ="AttendanceSystem.IService1" behaviorConfiguration="BasicHttpBinding_IService1">
<endpoint address="" binding="basicHttpBinding" contract="AttendanceSystem.IService1"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="BasicHttpBinding_IService1">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
And here is the reference to the service in the silverlight app
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:48886/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
name="default" />
</client>
</system.serviceModel>
Fiddler returns the following message on the call to my .svc service file:
HTTP/1.1 400 Bad Request
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 15 Jan 2014 09:17:26 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Length: 0
Connection: Close
So what is going on?
UPDATE: the service seems to be working without error when I pass a smaller byte array (for example BitConverter.GetBytes(123) but fails when the image is sent which is clearly within the max limits)
Try to configure the binding server-side (maxReceivedMessageSize and reader quotas)
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>

How to get the response and request in JSON format?

I'm not getting the output in JSON Format. Here is the code
---- IService1.cs ----
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "currency")]
List<Employee> GetAllEmployeesMethod();
[OperationContract]
string TestMethod();
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "players")]
List<Person> GetPlayers();
}
---- Service1.svc.cs ----
public List<Employee> GetAllEmployeesMethod()
{
List<Employee> mylist = new List<Employee>();
using (SqlConnection conn = new SqlConnection("--connection string--"))
{
conn.Open();
string cmdStr = String.Format("Select customercode,CurrencyCode,CurrencyDesc from Currency");
SqlCommand cmd = new SqlCommand(cmdStr, conn);
SqlDataReader rd = cmd.ExecuteReader();
if (rd.HasRows)
{
while (rd.Read())
mylist.Add(new Employee(rd.GetInt32(0), rd.GetString(1), rd.GetString(2)));
}
conn.Close();
}
return mylist;
}
---- web.config ----
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<authentication mode="Windows"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
<system.serviceModel>
<services>
<service name="JSONSerialization.Service1" behaviorConfiguration="EmpServiceBehaviour">
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" contract="JSONSerialization.IService1" behaviorConfiguration="web" >
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="EmpServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp automaticFormatSelectionEnabled="true" defaultOutgoingResponseFormat="Json" helpEnabled="true" defaultBodyStyle="Bare"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
and when I run this service, I get the data in
but I want the result to be in JSON format
Example: {"currencycode":"INR","DESCRIPTION":"Indian Rupees","customercode" : "1001"},....
add [Serialize] attribute to your methods

Categories