I have got a WCF service from one of my users. I want to check whether the service is working or not without adding any proxy. Is there any way that I can achieve this in my C# code?
You may achieve this by implementing an endpoint at WCF and querying it from the client.
Following is the WCF code I would use.
// Used for communication between WCF and client. Must be implemented both WCF and client sides
public class Response {
public int Id { get; set; }
public string Data { get; set; }
}
// Web Service - Interface
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Up")]
string CheckLogin();
}
// Web service - Implementation
public class ServiceImplementation : IService
{
public Response isUp()
{
Response response = new Response();
response.ID = 200;
response.Data = "web service is up";
return response;
}
}
Following is the client method to test if the service is up.
public bool CheckIfUp(string encodedUrl)
{
WebRequest request;
WebResponse ws;
Response response = new Response();
string url = "http://servicePath/isUp"; // your wcf url
try
{
request = WebRequest.Create(url);
ws = request.GetResponse();
return (response.ID == 200);
}
catch (Exception e)
{
Console.Write(e.StackTrace);
}
return false;
}
Hope this helps.
Try appending ?wsdl at the of the URL pointing to the WCF-service.
If your Web service address is
http://services.aonaware.com/DictService/DictService.asmx
you can reach your wsdl file like this:
http://services.aonaware.com/DictService/DictService.asmx?WSDL
The returned WSDL allows you to see all the method the WCF-service provides.
Is there any way to restrict Operation to only available to REST consumers and not to SOAP consumers?
For example:
[OperationContract]
List<Response> GetResponses(int orderID);
[OperationContract]
[WebGet(UriTemplate = "{orderID}/responses",
ResponseFormat = WebMessageFormat.Json)]
List<Response> GetResponses(string orderID);
While REST consumers can only tackle second method, SOAP consumers see both methods, but in any case they should use first method. So I want to show first method to SOAP consumers only and second to REST consumers only. Can I achieve my goal without creating new service?
What you can do is to separate contracts, one for the SOAP exposed, second for the REST exposed, and then make your service implement both :
SOAP contract
[ServiceContract]
public interface IDummySoap
{
[OperationContract]
List<Response> GetResponses(int orderID);
}
REST contract
[ServiceContract]
public interface IDummyRest
{
[OperationContract]
[WebGet(UriTemplate = "{orderID}/responses",
ResponseFormat = WebMessageFormat.Json)]
List<Response> GetResponses(string orderID);
}
Service implementation
public class DummyService : IDummySoap, IDummyRest
{
public List<Response> GetResponses(int orderID)
{
// Implementation
}
public List<Response> GetResponses(string orderID)
{
// Implementation
}
}
Then those who want to call your service by SOAP will use the SOAP contract and the others the REST contract.
There is a WCF-service in C#:
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class SubscriptionService : ISubscriptionService
{
public Message Help(Message m)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html; charset=utf-8";
return new WebHttpHelpPageMessage();
}
}
[ServiceContract]
interface ISubscriptionService
{
[OperationContract]
[WebInvoke(UriTemplate = "*", Method = "*")]
Message Help(Message m);
}
Message from the inherited class:
public class WebHttpHelpPageMessage : Message
{
...
protected override void OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer)
{
writer.WriteStartElement("html");
writer.WriteRaw("<head></head><body><p>Hi</p></body>");
writer.WriteEndElement();
}
}
The result in the browser - XML, how to do it to be HTML?
since you already have got the xml what i can suggest you to do is create an xml object. And then, create xslt (http://msdn.microsoft.com/en-us/library/ms256069.aspx) as per you desire.
Then you can transform that xml in to HTML using xslt. It's easy that way and you have the control over how you want to display that.
(http://msdn.microsoft.com/en-us/library/system.xml.xsl.xslcompiledtransform.aspx)
This is good enough if you follow this approach.
What is the best practice for multiple WCF end point types? i.e.: JSON, JSONP, SOAP & POX? I am using WCF 3.5.
For instance, I have the following JSONP web service:
namespace RivWorks.Web.Service.JSONP
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract(Name = "Negotiate", Namespace = "http://rivworks.com/Services/2009/01/15")]
public class Negotiate //: svcContracts.INegotiateService
{
#region Constructors
public NegotiateService() { }
#endregion
#region Methods
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public dto.NegotiateSetup GetSetup(string method, string jsonInput)
{ … }
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public List<dto.NegotiateSetup> GetSetupAll(string method, string jsonInput)
{ … }
#endregion
}
}
Now, I need to expose a SOAP and POX version. My initial thought was to create a WCF Application Project for each service type endpoint. Then publish each one to an App directory under the main website.
RivWorks.Web.Service.SOAP -> http://rivworks.com/services/soap
RivWorks.Web.Service.POX -> http://rivworks.com/services/pox
RivWorks.Web.Service.JSON -> http://rivworks.com/services/json
RivWorks.Web.Service.JSONP -> http://rivworks.com/services/jsonp
I have an internal “Bus” that the working code lives in. I just want to wrap that bus code with service endpoints of various types. What is the best practice way to do this?
PS: Is there a tool for merging the WCF web.config(s) into the main site’s web.config?
TIA
-kb
UPDATE:
How do you go about handling the different decorators that can be applied to a Method signature. i.e. - compare the following Methods (which are identical) and the decorators associated with them:
Decorator for a POX endpoint:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
public bool ValidateUser(string UserName, string Password)
{
...
}
vs
Decorator for a JSON endpoint:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public bool ValidateUser(string UserName, string Password)
{
...
}
And here is another example where the method signature itself changes:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public dto.NegotiateSetup GetSetup(string method, string jsonInput)
{
// Deserialize the input and get all the data we need...
JObject o = Newtonsoft.Json.Linq.JObject.Parse(jsonInput);
string urlRef = String.Format("{0}", o["ref"]).Drop("\"");
string clientDate = String.Format("{0}", o["dt"]).Drop("\"");
string stringProductID = String.Format("({0})", o["productId"]).Drop("\"").Drop("(").Drop(")");
string SKU = String.Format("{0}", o["sku"]).Drop("\"");
string env = String.Format("{0}", o["env"]).Drop("\"");
string stringCompanyID = String.Format("({0})", o["CompanyId"]).Drop("\"").Drop("(").Drop(")");
string boolPortalFlag = String.Format("({0})", o["PortalFlag"]).Drop("\"").Drop("(").Drop(")");
...
}
vs a POX endpoint type:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
public dto.NegotiateSetup GetSetup(string urlRef, string clientDate, string stringProductID, string SKU, string env, string stringCompanyID, string boolPortalFlag)
{
...
}
Why would you want a separate project? WCF can expose many services on many endpoints, just in a single project.
Simply add the additional endpoints as .svc files. Do whatever you need to do with routing if you're sensitive to the ".svc" at the end (though remember that humans don't see the .svc).
How do I access the HTTP POST request body in a WCF REST service?
Here is the service definition:
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "EntryPoint")]
MyData GetData();
}
Here is the implementation:
public MyData GetData()
{
return new MyData();
}
I though of using the following code to access the HTTP request:
IncomingWebRequestContext context = WebOperationContext.Current.IncomingRequest;
But the IncomingWebRequestContext only gives access to the headers, not the body.
Thanks.
Best way i think doesn't involve WebOperationContext
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "EntryPoint", BodyStyle = WebMessageBodyStyle.Bare)]
MyData GetData(System.IO.Stream pStream);
Use
OperationContext.Current.RequestContext.RequestMessage
Sorry for the late answer but I thought I would add what works with UriTemplate parameters to get the request body.
[ServiceContract]
public class Service
{
[OperationContract]
[WebInvoke(UriTemplate = "{param0}/{param1}", Method = "POST")]
public Stream TestPost(string param0, string param1)
{
string body = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
return ...;
}
}
body is assigned a string from the raw bytes of the message body.
This code return body text. Need using System, System.Text, System.Reflection, System.ServiceModel
public string GetBody()
{
var requestMessage = OperationContext.Current.RequestContext.RequestMessage;
var messageDataProperty = requestMessage.GetType().GetProperty("MessageData", (BindingFlags)0x1FFFFFF);
var messageData = messageDataProperty.GetValue(requestMessage);
var bufferProperty = messageData.GetType().GetProperty("Buffer");
var buffer = bufferProperty.GetValue(messageData) as ArraySegment<byte>?;
var body = Encoding.UTF8.GetString(buffer.Value.Array);
return body;
}
I was able to solve my issue cobbling together multiple answers on this thread. What I am trying to do is to receive a JSON payload in the body of the POST and not have anything done to it so that I can parse it as I will. This is important to us because the JSON coming in is not a single predetermined thing, but rather one of several possible. Yes, we could add a separate call for each new thing, but we are trying to allow the system to be extensible without code changes.
In previous attempts I have only been able to get this to work if the content type was 'text/plain', but then I'm sitting chewing on my tongue explaining why it can't be sent as 'application/json' when someone wants to call it.
So... from the answers on this page... the following signature:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "test/", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
void TestCall();
and then getting the JSON from the body like so:
private string GetJSONFromBody()
{
string json = "";
string contentType = WebOperationContext.Current.IncomingRequest.ContentType;
if (contentType.Contains("application/json"))
{
var requestMessage = OperationContext.Current.RequestContext.RequestMessage;
var messageDataProperty = requestMessage.GetType().GetProperty("MessageData", (BindingFlags)0x1FFFFFF);
var messageData = messageDataProperty.GetValue(requestMessage);
var bufferProperty = messageData.GetType().GetProperty("Buffer");
var buffer = bufferProperty.GetValue(messageData) as ArraySegment<byte>?;
json = Encoding.UTF8.GetString(buffer.Value.Array);
}
else if (contentType.Contains("text"))
{
json = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
}
return json;
}
This way however someone tries to send the JSON it will work, but at last I was able to support 'application/json'. I still needed to support 'text/plain' since there are already apps calling that way.
The above answers helped me come up with this solution. I am receiving json with name/value pairs. {"p1":7514,"p2":3412, "p3":"joe smith" ... }
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json
)]
public Stream getJsonRequest()
{
// Get the raw json POST content. .Net has this in XML string..
string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString();
// Parse the XML string into a XML document
XmlDocument doc = new XmlDocument();
doc.LoadXml(JSONstring);
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
{
node.Name // has key
node.InnerText; // has value
It seems that because WCF is designed to be transport protocol-agnostic, a service method doesn't provide access to HTTP-specific information by default. However, I just came across a nice article describing "ASP.Net Compatibility Mode" which essentially allows you to specify that your service is indeed intended to be exposed via HTTP.
Link
Adding the aspNetCompatibilityEnabled configuration to Web.config, combined with the AspNetCompatibilityRequirements attribute to the desired service operations, should do the trick. I'm about to try this myself.
Haw-Bin
My apologies for the previous answer, I stupidly assumed that I had just cast WebOperationContext to get at the OperationContext, unfortunately the real answer is much more ugly.
Let me preface this with, there must be a better way!
First I created my own context object, that could be attached to the existing OperationContext object.
public class TMRequestContext : IExtension<OperationContext> {
private OperationContext _Owner;
public void Attach(OperationContext owner) {
_Owner = owner;
}
public void Detach(OperationContext owner) {
_Owner = null;
}
public static TMRequestContext Current {
get {
if (OperationContext.Current != null) {
return OperationContext.Current.Extensions.Find<TMRequestContext>();
} else {
return null;
}
}
}
}
In order to be able to access this new context object, you need to add it as an extension to the current one. I did that by creating a message inspector class.
public class TMMessageInspector : IDispatchMessageInspector {
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) {
OperationContext.Current.Extensions.Add(new TMRequestContext());
return null;
}
}
In order for the message inspector to work you need to create a new "behaviour". I did this using the following code.
public class TMServerBehavior : IServiceBehavior {
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) {
//Do nothing
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) {
foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher epDisp in chDisp.Endpoints) {
epDisp.DispatchRuntime.MessageInspectors.Add(new TMMessageInspector());
}
}
}
}
The behaviour you should be able to add in the config file, although I did it by creating a new host and adding the behaviour object manually in the OnOpening method. I ended up using these class for much more than just accessing the OperationContext object. I used them for logging and overriding the error handling and access to the http request object,etc. So, it is not quite as ridiculous solution as it seems. Almost, but not quite!
I really don't remember why I could not just access OperationContext.Current directly. I have a faint recollection that it was always empty and this nasty process was the only way I could get an instance that actually contained valid data.
Here is what I did:
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
namespace YourSpaceName
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class YourClassName
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "YourMethodName({id})", BodyStyle = WebMessageBodyStyle.Bare)]
public Stream YourMethodName(Stream input, string id)
{
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.Headers.Add("Content-Type", "application/json");
string response = $#"{{""status"": ""failure"", ""message"": ""Please specify the Id of the vehicle requisition to retrieve."", ""d"":null}}";
try
{
string response = (new StreamReader(input)).ReadToEnd();
}
catch (Exception ecp)
{
response = $#"{{""status"": ""failure"", ""message"": ""{ecp.Message}"", ""d"":null}}";
}
return new MemoryStream(Encoding.UTF8.GetBytes(response));
}
}
}
This code simply reads the input and writes it out.
the body of the POST request is automatically assigned to input irrespect of the variable name. As you can see, you can still have variables in your your UriTemplate.