I created WCF service and calling it from the android studio and its working fine, but after implementing WCF perSession functionality it is working for a single user at a time.
Problem:
My problem is when i am hitting WCF url with multiple user my sessionID get overwrite by the latest logged in user, So how to maintain session for multiple user like we do in web application.
I used this to creste session in WCF:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
and this is my method to create sessionid within services class
public class MyService : IMyService
{
static string currentSessionID = string.Empty;
public string createSession()
{
currentSessionID = DateTime.Now.Ticks.ToString();
return currentSessionID;
}
public string Login()
{
var mysessionId = createSession();
return mysessionId;
}
public string Mymethods(string data)
{
string response = "";
if(data.StartsWith("01"))
response = Login();
return response;
}
}
and am hitting this createSession() method only in login function.
Please help me out of this.....
Thanks in advnance.
I'm having trouble with implementing URL redirection using message inspectors for my WCF REST service. The idea is to implement AfterReceiveRequest to change the incoming request to effectively do nothing, and then in BeforeSendReply, make call to another URI which provides the actual service. You can think of this scenario as something where we do not want to break clients, so they continue to use old URIs for invocations, but internally we redirect them to a different URI.
For example, this is what my service contract looks like:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "person/{person}")]
string GreetMe(string person);
[OperationContract]
[WebGet(UriTemplate = "donothing")]
string DoNothing();
}
And this is the implementation:
public class Service1 : IService1
{
public string GreetMe(string person)
{
return string.Format("Hi {0}", person);
}
public string DoNothing()
{
return string.Empty;
}
}
Then I'm adding a MessageInspector to endpoint behavior. The AfterReceiveRequest of this inspector is like this:
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
OperationContext operationContext = OperationContext.Current;
if (WebOperationContext.Current != null && WebOperationContext.Current.IncomingRequest.UriTemplateMatch != null)
{
UriBuilder baseUriBuilder = new UriBuilder(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri);
UriBuilder requestUriBuilder = new UriBuilder(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri);
OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = baseUriBuilder.Uri.ToString();
OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = baseUriBuilder.Uri.ToString() + "donothing";
OperationContext.Current.IncomingMessageHeaders.To = new Uri(baseUriBuilder.Uri.ToString() + "donothing");
operationContext.IncomingMessageProperties["Via"] = new Uri(baseUriBuilder.Uri.ToString() + "donothing");
request.Headers.To = new Uri(baseUriBuilder.Uri.ToString() + "donothing");
}
return null;
}
Basically, I want to change all incoming requests to go to DoNothing() operation. However, when I run this, I still see that the request makes it to GreetMe method. I attached the debugger and can see that my code in AfterReceiveRequest is getting executed, but I'm not sure why the URI redirection does not happen.
Any ideas?
I'm fairly new to programming an C# and i need to create a web application project. I have been told that a website will navigate to my web application and send an ID. My web application then needs to use this ID within a SOAP request. The responce then needs to be evaluated and if it fits a criteria, the web application can load or else just throws an exception.
I can code all the application except grabbing the initial ID and setting up a SOAP request and recieve. I have all the relevant information, i just don't know how to set up the SOAP request/responce.
Best Regards
Assuming you are using a WCF, it uses SOAP by default, so if you have everything setup correctly, it will automatically serialize and deserialize for you.
[OperationContract]
MyResponse ParseId(MyRequest req);
MyResponse can hold response information
MyRequest can hold request information
Implementation could be like this:
public MyResponse ParseId(MyRequest req)
{
if(req.Id == null)
{
//Error
}
else
{
}
}
If it is really simple, you can do something like this:
[OperationContract]
void ParseId(int id);
Implementation:
public void ParseId(int id)
{
if(id == null)
{
//throw exception;
}
else
{
}
}
Don't forget to decorate your MyResponse class and MyRequest class with DataContract attributes.
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.