I am new to WCF i am trying to implement WCF Session Management but i am not clear about how to implement the session in WCF
This is my CODE
<wsHttpBinding>
<binding name="wsHttpBinding">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples",
SessionMode=SessionMode.Required)]
public interface IMyService
{
...
}
This is not working...session is not maintained in my project
Now i wanted to know whether am missing anything or whether i need to add anything else in client or server side???? or this alone is enough to implement the session in my project???
It will be of great help if someone provide some ideas,suggestions,or sample code for implementing my task...
When you implement your IMyService in a class and a client connects to your service every client gains a new instance of your class.
There is a little example, that might help you:
http://www.devx.com/architect/Article/40665
How your service will behave depends not just on the SessionMode specified for the ServiceContract, but also on the InstanceContextMode under which your service implementation runs (controlled by the InstanceContextMode property of the ServiceBehavior). There is a helpful table here which tells you what to expect with the various combinations of these settings.
If this doesn't help solve your problem, please explain more specifically what behaviour you are expecting and what you are seeing.
Related
I am new to WCF, I am facing concurrency related issue in my hosted wcf service (.net framework 4.0) on IIS 7 / Windows 2008 server. I did all the possibilities after googling but still not able to fix my problem. I have created and inventory service which uses Entity Framework to fetch data from SQL Server tables like ItemHeadMaster, ItemMaster etc.
I referenced this WCF in my custom user search control for searching purposes. All is running well when 2 concurrent user hit search control placed on ASP.Net page.
My code looks like this:
namespace HIS.STORESERVICES
{
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class StoreMasterData : IStoreMasterData
{
public string GetAllItemHead(string strHospitalId)
{
using (DAL.ItemHeadMaster objItemHeadMasterDAL = new DAL.ItemHeadMaster())
{
List<STORE.MODEL.ItemHeadMaster> objItemHeamMasterList = new List<STORE.MODEL.ItemHeadMaster>();
objItemHeamMasterList = objItemHeadMasterDAL.GetAllItemHead(strHospitalId);
XmlSerializer Xml_Serializer = new XmlSerializer(objItemHeamMasterList.GetType());
StringWriter Writer = new StringWriter();
Xml_Serializer.Serialize(Writer, objItemHeamMasterList);
return Writer.ToString();
}
}
}
I did following after googling:
added in config but NO EFFECT
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>`
Added in config but NO EFFECT instead it gets more slow..
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" />
<serviceThrottling maxConcurrentCalls="32"
maxConcurrentInstances="2147483647"
maxConcurrentSessions="20"/>
Please help
Before WCF, to construct a service for cross process communications between processes in the same host, or in the same LAN, or in the Internet, you have to hand-craft transportation layers and data serializations for target environments and specific protocols.
With WCF, you just need to focus on creating data models (DataContracts after being decorated by attributes) and operation models (OperationContracts), and .NET CLR will "create" most if not all needed transportation layers and data serializations at run time, according to the configuration defined by you or the system administration in the target environment.
The defects in your codes:
WCF typically uses DataContractSerializer, NOT Xmlserializer to serialize things, and you don't need to call it explicitly, since the runtime will do it.
For most applications, you don't need ServiceBehaviorAttribute explicitly. You must know WCF in depth before using those advantage config which is not for beginner. And I rarely used them.
Your service interface function should comfortably return complex type rather the serialized text. In 99.9% of cases, if you have explicit serialization codes in WCF programs, the whole design is very dirty if not entirely wrong.
There are plenty of tutorials of creating Hello World WCF projects, and VS has one for you when creating a new WCF application. After you got familiar with Hello World, you may have a look at http://www.codeproject.com/Articles/627240/WCF-for-the-Real-World-Not-Hello-World
BTW, WCF serialization is very fast, check http://webandlife.blogspot.com.au/2014/05/performances-of-deep-cloning-and.html
My ASP.NET MVC3 application uses Ninject to instantiate service instances through a wrapper. The controller's constructor has an IMyService parameter and the action methods call myService.SomeRoutine(). The service (WCF) is accessed over SSL with a wsHttpBinding.
I have a search routine that can return so many results that it exceeds the maximum I have configured in WCF (Maximum number of items that can be serialized or deserialized in an object graph). When this happens, the application pools for both the service and the client grow noticeably and remain bloated well past the end of the request.
I know that I can restrict the number of results or use DTOs to reduce the amount of data being transmitted. That said, I want to fix what appears to be a memory leak.
Using CLR Profiler, I see that the bulk of the heap is used by the following:
System.RunTime.IOThreadTimer.TimerManager
System.RunTime.IOThreadTimer.TimerGroup
System.RunTime.IOThreadTimer.TimerQueue
System.ServiceModel.Security.SecuritySessionServerSettings
System.ServiceModel.Channels.SecurityChannelListener
System.ServiceModel.Channels.HttpsChannelListener
System.ServiceModel.Channels.TextMessageEncoderFactory
System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder
System.Runtime.SynchronizedPool
System.Runtime.SynchronizedPool.Entry[]
...TextMessageEncoderFactory.TextMessageEncoder.TextBufferedMessageWriter
System.Runtime.SynchronizedPool.GlobalPool
System.ServiceModel.Channels.BufferManagerOutputStream
System.Byte[][]
System.Byte[] (92%)
In addition, if I modify the search routine to return an empty list (while the NHibernate stuff still goes on in the background - verified via logging), the application pool sizes remain unchanged. If the search routine returns significant results without an exception, the application pool sizes remain unchanged. I believe the leak occurs when the list of objects is serialized and results in an exception.
I upgraded to the newest Ninject and I used log4net to verify that the service client was closed or aborted depending on its state (and the state was never faulted). The only thing I found interesting was that the service wrapper was being finalized and not explicitly disposed.
I'm having difficulty troubleshooting this to find out why my application pools aren't releasing memory in this scenario. What else should I be looking at?
UPDATE: Here's the binding...
<wsHttpBinding>
<binding name="wsMyBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:02:00" sendTimeout="00:02:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="999999" maxReceivedMessageSize="99999999"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false"
allowCookies="false">
<readerQuotas maxDepth="90" maxStringContentLength="99999"
maxArrayLength="99999999" maxBytesPerRead="99999"
maxNameTableCharCount="16384" />
<reliableSession enabled="false" />
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
UPDATE #2: Here is the Ninject binding but more curious is the error message. My wrapper wasn't setting MaxItemsInObjectGraph properly so it used the default. Once I set this, the leak went away. Seems that the client and service keep the serialized/deserialized data in memory when the service sends the serialized data to the client and the client rejects it because it exceeds MaxItemsInObjectGraph.
Ninject Binding:
Bind<IMyService>().ToMethod(x =>
new ServiceWrapper<IMyService>("MyServiceEndpoint")
.Channel).InRequestScope();
Error Message:
The InnerException message was 'Maximum number of items that can be
serialized or deserialized in an object graph is '65536'
This doesn't actually fix the memory leak so I am still curious as to what have been causing it if anyone has any ideas.
How are you handling your proxy client creation and disposal?
I've found the most common cause of WCF-related memory leaks is mishandling WCF proxy clients.
I suggest at the very least wrapping your clients with a using block kinda like this:
using (var client = new WhateverProxyClient())
{
// your code goes here
}
This ensures that the client is properly closed and disposed of, freeing memory.
This method is a bit controversial though, but it should remove the possibility of leaking memory from client creation.
Take a look here for more on this topic.
I am new to WCF,my task is to create,maintain sessions in WCF
I have a requirement in my project,what it says is I need to have a service(WCF) which has to be session enabled.More than one client will contact the above said service and the service has to deliver the required information that client wants.
For example: The service will hold a DOM object,here DOM means a database object which will have say Employee information.Each client will ask for different information from the DOM object,and our service has to deliver the information.Our servvice should not goto Database each time when the client calls,so for this we need to implement session management in service(WCF).
It will be of great help if someone provide some ideas,suggestions,or sample code for implementing my task...
Thanks...
First I'll point out that it is usually a very bad idea to use sessions with WCF. Having too many sessions open will consume lots of resources (eg memory and database connections). You mentioned that you are also storing database objects in the session - this is also likely to end up hurting you as most databases only allow a limited number of sessions.
All that said, if you really need to use sessions, there is some info for configuring it on MSDN.
You can configure your binding to use sessions as follows:
<wsHttpBinding>
<binding name="wsHttpBinding">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
You can then mark your ServiceContract with SessionMode=SessionMode.Required:
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples",
SessionMode=SessionMode.Required)]
public interface IMyService
{
...
}
In my solution I have a Web application project and a Class library project that contains all the business logic and this also acts as a data access layer as I am using Entity Framework. This means that I have my edmx in this layer itself.
I have some 34 classes in this class library project and at an average 6 public methods in each class. These classes were getting called directly from the web application until now. No problems. Now I want to introduce the WCF Layer between the UI and the Business logic layer.
This means I will have to write wrapper methods for all my methods and expose them in a WCF Service. Does this mean that 34 * 6 = 204 methods (approximately) will appear in my service layer as Operation Contracts? As per OO, I think this is too large a class and so it feels wrong.
I know there is the Generic Service design pattern, but is there anything else that I am missing? Please advise.
You could try RIA services
http://www.silverlight.net/getstarted/riaservices/
What I'm using is this.
Create a WCF service
2.1. Point the SVC service to your implementation like:
<%# ServiceHost Language="C#" Debug="true" Service="BusinessLayer.Service" %>
BusinessLayer.Service is a class in your Class project. (reference in service is needed)
2.2. Point the service behavior to the contract:
<service behaviorConfiguration="ServiceBehavior" name="BusinessLayer.Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding" contract="BusinessLayer.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</service>
Edit the name (BusinessLayer.Service) and contract (Businesslayer.IService)
Create the contract interface BusinessLayer.IService (in your Class project):
namespace BusinessLayer
{
[ServiceContract]
public interface IService
{
[OperationContract]
void DoWork();
}
}
Modify the existing implementation which uses the interface (here is your existing code):
namespace BusinessLayer
{
public class Service:IService
{
Public void DoWork()
{
}
}
}
Why do you want to wrap the entire business logic layer in a WCF layer? I would look very closely at your reasons for this before jumping into this new approach. Do you have physical reasons that you simply can't get around like the business logic that accesses the database needing to be outside the DMZ? If so, ok. But if not, I'd think twice about going down this approach to start with.
Having said that, if you have no other choice, I'd avoid the monolithic WCF class that wraps every public method that your UI needs. First off, I'd introduce an interface on the web application side so that you can depend on abstracts in the UI rather than concrete implementations. Further, I'd look into using WCF REST services. You can use ServiceRoute's to avoid having to introduce any *.svc files. Then you can decorate the methods you want to expose with WebGet/WebInvoke attributes. This could potentially save a lot of coding.
Well,
We have a similar application but the number of classes is even higher. Your concern here is that you are reluctant to provide serialization (that is what is needed to pass objects by WCF) to core classes of your business logic server.
Provided you have a classical three-tier application where business logic server and a client access the same database. What you need to do is simply 1) ensure all your objects have a unique identification (this could be a string or Guid) and 2) pass object ID in all WCF calls. What that means is that you DO NOT expose any classes on WCF side.
This might be quite is safer since you have a web application.
It is wrong. Your services should not have much more than 20 operations. If you need exactly same operations you should create contract and service wrapper for each business class. This usually results in chatty interfaces which are not good solution for distributed scenario. In that case you should model your service layer as facade which compounds several calls into one.
I've written a custom binding class that inherits from CustomBinding.
My custom class overrides the BuildChannelFactory method and uses a custom ChannelFactory to create a custom channel.
I'm having difficulties using the custom binding class in the WCF client.
I am able to use my custom binding class if I configure it in code:
Binding myCustomBinding = new MyCustomBinding();
ChannelFactory<ICustomerService> factory =
new ChannelFactory<ICustomerService>(myCustomBinding,
new EndpointAddress("http://localhost:8001/MyWcfServices/CustomerService/"));
ICustomerService serviceProxy = factory.CreateChannel();
serviceProxy.GetData(5);
My problem is I don't know how to configure it in the App.config file.
Is it a customBinding element, or a bindingExtension element? Is it something else?
When you created your custom binding in code, did you also implement a "YourBindingElement" (deriving from StandardBindingElement) and a "YourBindingCollectionElement" (deriving from StandardBindingCollectionElement) along with it?
If so - use that to configure your custom binding, as if it were any other binding.
The first step is to register your binding in the app.config or web.config file in the extensions section of <system.serviceModel>
<extensions>
<bindingExtensions>
<add name="yourBindingName"
type="YourBinding.YourBindingCollectionElement, YourBindingAssembly" />
</bindingExtensions>
</extensions>
Now, your new binding is registered as a "normal" available binding in WCF. Specify your specifics in the bindings section as for other bindings, too:
<bindings>
<yourBinding>
<binding name="yourBindingConfig"
proxyAddress="...." useDefaultWebProxy="false" />
</yourBinding>
</bindings>
Specify other parameters here, as defined in your "...BindingElement" class.
Lastly, use your binding like a normal binding in your services and/or client sections in system.serviceModel:
<client>
<endpoint
address="....your url here......"
binding="yourBinding"
bindingConfiguration="yourBindingConfig"
contract="IYourContract"
name="YourClientEndpointName" />
</client>
I couldn't really find a lot of resources on how to write your own binding in code on the web - Microsoft has a WCF/WPF/WF sample kit which includes a few samples from which I basically learned enough to figure it out :-)
There's one really good article by Michele Leroux Bustamante on creating your custom bindings - part 2 of a series, but part 1 is not available publicly :-(
Here's a sample custom binding in code for which you can download the complete source code: ClearUserNameBinding.
Marc
If you want to use this custom binding via configuration, you must extend the BindingCollectionElement abstract base and define bindingExtensions element in web.config.