I have WCF Service, my goal is to be able to retrieve information from my server using GET and POST. I almost got it to work. My problem is that to be able to access the information on the server I need to enter my credentials, otherwise I get the error 401 unauthorized
I tried a few different things but I'm still new at using XML and when I try to add some code I always get errors.
This is my code:
C#
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "xml/{id}")]
string XMLData(string id);
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "json/{id}")]
string JSONData(string id);
}
XML
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- 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>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
I still don't know how to fix this.
Try this (link to code download below listing):
// IRestService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace RestService
{
// 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 IRestServiceImpl
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "xml/{id}")]
string XMLData(string id);
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "json/{id}")]
string JSONData(string id);
}
}
// RestService.cs
namespace RestService
{
public class RestServiceImpl : IRestServiceImpl
{
public string JSONData(string id)
{
return id;
}
public string XMLData(string id)
{
return id;
}
}
}
<!-- RestService.svc (Source) -->
<%# ServiceHost Language="C#" Debug="true" Service="RestService.RestServiceImpl" CodeBehind="RestService.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
<!-- Web.config -->
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows">
</transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="false" includeWindowsGroups="true" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Results below (your base URL will likely differ). Ignore the "Endpoint not found" message you see. Rest services should not expose metadata (unless HATEOAS is considered metadata in your mind :)
http://localhost:62001/RestService.svc/xml/absee
<XMLDataResponse xmlns="http://tempuri.org/">
<XMLDataResult>absee</XMLDataResult>
</XMLDataResponse>
http://localhost:62001/RestService.svc/json/absee
{"JSONDataResult":"absee"}
Download the code here
You may want to set it to run under IIS Express in the project settings under the Web tab.
Related
I want to build a WCF service that will return a JsonP request. I want it to return the following,
jsonpCallback({"fileNames":"IDR023.T.201705201412.png, IDR023.T.201705201418.png"});
So I created the following WCF Service
IBOM.cs
[ServiceContract]
public interface IBOM
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
string GetData();
}
BOM.cs
public class BOM : IBOM
{
public string GetData()
{
return "jsonpCallback({\"fileNames\":\"IDR023.T.201705201412.png, IDR023.T.201705201418.png\"});";
}
}
Webconfig
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="BomService.BOM" behaviorConfiguration="ServiceBehaviour">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="webHttpBinding" contract="BomService.IBOM" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- 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>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
But I am getting back
"jsonpCallback({\"fileNames\":\"IDR023.T.201705201412.png, IDR023.T.201705201418.png\"});"
I am returning a string and trying to set it up to return what I need. Is this the best way for JSONP? or is there a better way to achieve what I need
Thanks
For anyone who is interested, I worked it out. Here is the code.
IBOM
[ServiceContract]
public interface IBOM
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
Stream GetData();
}
BOM
public class BOM : IBOM
{
public Stream GetData()
{
string jsCode = "jsonpCallback" + "({\Test:\"" + fileNames + "\"});";
WebOperationContext.Current.OutgoingResponse.ContentType = "application/javascript";
return new MemoryStream(Encoding.UTF8.GetBytes(jsCode));
}
I am trying to create a WCF Service for https binding. The service was working with http before. I changed the binding (with certificate) and now I configure the web.config - but I always get error code "400 - Bad Request".
The web service is called with:
https://servername:444/FolderService.svc/FolderExists/1234
https://servername:444/FolderService.svc/Test
This is my service interface:
[ServiceContract]
public interface IFolderService
{
[OperationContract]
[WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/FolderExists/{accountnumber}")]
bool FolderExists(string accountnumber);
[OperationContract]
[WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/Test")]
string Test();
}
And this is my web.config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="myService.FolderService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="myService.IFolderService"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I tried so many different configuration without success. Does anyone have an idea (or a working example)?
Thanks in advance!
You are trying to access your methods in a RESTful manner via a URL. However, what you have wrong in your web.config is that you are using BasicHttpBinding which is for SOAP web services and not RESTful web services.
WebGet and WebInvoke are the necessary attributes to add to your operations as you have already done.
However, the correct binding for the endpoint is WebHttpBinding and the behavior you need to apply to the endpoint is the WebHttpBehavior.
Sample Abbreviated Configuration:
<service>
<endpoint behaviorConfiguration="webBehavior"
binding="webHttpBinding"
contract="myService.IFolderService"
bindingConfiguration="secureHttpBinding" />
</service>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
My service model looks as follows.
<system.serviceModel>
<services>
<service name="Web.General" behaviorConfiguration="common">
<endpoint address="basic"
binding="basicHttpBinding"
contract="Web.IGeneral" />
<endpoint
...
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="common">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
When I hit .../general.svc/ping/1 I get error 400 Bad Request, which I can't explain. What is that and how can I kill it?
My service has interface as follows.
[ServiceContract]
public interface IGeneral
{
//[OperationContract(Name = "Ping")]
[WebInvoke(
Method = "GET",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
//RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Ping/{input}")]
String Ping(String input);
}
Mate, I'v e been in to this situation and the best approach to solve this out is through Fiddler. 404 can be due to anything at server level. How about running a fiddler and see the RAW request - response
http://www.telerik.com/download/fiddler
Otherwise, enable WCF logging.
http://www.codeproject.com/Articles/383162/Logging-and-Tracing-WCF-Soap-Messages
And then use trace viewer:
http://msdn.microsoft.com/en-us/library/ms732023(v=vs.110).aspx
If you want us to give a concrete answer then you probably need to provide us more details.
I created WCF service. when i test it with WCF Test Client , the service works fine.
I decided to configure the end point to display the result using the browser.
I have a blank page with the text Endpoint not found. with no more details.
Here is my web.config
<system.serviceModel>
<services>
<service name="mCollectorService.CollectorService" behaviorConfiguration="mCollectorService.CollectorServiceBehavior">
<endpoint address="../CollectorService.svc"
binding="webHttpBinding"
contract="mCollectorService.ICollectorService"
behaviorConfiguration="webBehaviour"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mCollectorService.CollectorServiceBehavior">
<!-- 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="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Here is my ICollectorService
[ServiceContract]
public interface ICollectorService
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "Authenticate/{agentcode}/{pin}/{deviceIMEI}/{gpslat}/{gpslong}")]
Authentification Authenticate(string agentcode,string pin, string deviceIMEI, string gpslat, string gpslong);
}
Any Help.
Try modifying your Service like this:
<services>
<service name="mCollectorService.CollectorService" behaviorConfiguration="mCollectorService.CollectorServiceBehavior">
<endpoint address="../CollectorService.svc"
binding="webHttpBinding"
contract="mCollectorService.ICollectorService"
behaviorConfiguration="webBehaviour"
/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:51855/CollectorService.svc" />
</baseAddresses>
</host>
</service>
</services>
And Change your OperationContract
[ServiceContract]
public interface ICollectorService
{
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "Authenticate/{agentcode}/{pin}/{deviceIMEI}/{gpslat}/{gpslong}")]
Authentification Authenticate(string agentcode,string pin, string deviceIMEI, string gpslat, string gpslong);
}
And Call your URL in this way!
http://localhost:51855/CollectorService.svc/CollectorService.svc/Authenticate/YourAgentCode/YourPin/YourDeviceIMEI/YourGPSLat/YourGPSLong
Hope this will help. Thank You!
EDIT: I will recommend you to wrap your request in JSON instead of sending it in the Request URL if you are implementing Authentication mechanism.
I am writing a WCF Rest service to return a JSON message. I've been trying to use an example I found on the internet as a guide. Any time I fire up the test client, none of my methods are displayed. Navigating to the Uri while the service is running yields me a "page cannot be displayed" page. Not exactly too sure where to go from here. Any help would be appreciated.
Web Config:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJasonP"
crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<services>
<service name="WcfRestLicense.LicenseService"
behaviorConfiguration="WebServiceBehavior">
<endpoint behaviorConfiguration="jsonBehavior"
binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJasonP"
contract="WcfRestLicense.ILicenseService" />
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<!--<client />-->
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WebServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add
scheme="http"
binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJasonP" />
</protocolMapping>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="false"
multipleSiteBindingsEnabled="true" />
Service method:
public IQueryable<customer> GetCustomerById(string customerId)
{
int custId = Convert.ToInt32(customerId);
return _context.customers.Where(c => c.cust_id == custId);
}
Interface:
[ServiceContract]
public interface ILicenseService
{
[OperationContract]
[WebGet(UriTemplate = "customer/{customerId}/",
RequestFormat= WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
IQueryable<customer> GetCustomerById(string customerId);
}
If by test client you're talking about the WcfTestClient, then it won't work with RESTful services; it's designed to work with SOAP based web services. You can test RESTful services in a browser by passing in the appropriate URI, something like this:
http://<location of your service>/service/1
Where the number 1 would be a customer ID. This is a rough example as a) I don't do a lot with RESTful services and b) I'm not sure what your actual address is.
As far as getting a 404 when you go to the Uri, it sounds like you're looking for the help page. You can enable that in your config file:
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJasonP"
crossDomainScriptAccessEnabled="true"
enableHelp="true" />
</webHttpBinding>
</bindings>