WCF Restful Service static variable - wcf

I currently have 2 static dictionaries in a wcf restful service. These both hold look up data that's not worth putting in a database. Will these stay in memory until the application restarts or should I put them in HttpContext.Current.Application?

The static data will remain until the process recycles or stops, the same as HttpContext.Current.Application.
If you are looking for a more sophisticated caching option, check out the System.Runtime.Caching namespace introduced in 4.0. It is easy to use, works in any .NET application, and offers features like setting expiration times and creating callback functions to execute on expire.

Related

Can a BackgroundService run indefinitely in ASP .NET Core 3.1?

I am constructing a web service that receives data and updates it periodically. When a user pings the service, it will send specific data back to the user. In order to receive this data, I have a persistent that is created on startup and regularly receives updates, but not at periodic intervals. I have already implemented it, but I would like to add DI and make it into a service. Can this type of problem be solved with a BackgroundService or is this not recommended? Is there anything better I should use? I originally wanted to just register my connection object as a singleton, but since singletons are not initialized on startup, that does not work so well for me.
I thought I would add an answer as so expand on my comment. From what you have described, creating a BackgroundService is likely the best solution for what you want to do.
ASP.NET Core provides an IHostedService interface that can be used to implement a background task or service, in your web app. They also provide a BackgroundService class that implements IHostedService and provides a base class for implementing long running background services. These background services are registered within the CreateWebHostBuilder method in Program.cs.
You can consume services from the dependency injection container but you will have to properly manage their scopes when using them. You can decide how to manage your BackgroundService classes in order to fit your needs. It does take an understanding of how to work with Task objects and executing, queueing, monitoring them etc. So I'd recommend giving the docs a thorough read, so you don't end up impacting performance or resource usage.
I also tend to use Autofac as my DI container rather than the built in Microsoft container, since Autofac provides more features for resolving services and managing scopes. So it's worth considering if you find yourself hitting a wall because of the built in container.
Here's the link to the docs section covering this in much more depth. I believe you can also create standalone service workers now, so that might be worth a look depending on use case.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio
Edit: Here's another link to a guide an example implementation for a microservice background service. It goes a little more in depth on some of the specifics.
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice#implementing-ihostedservice-with-a-custom-hosted-service-class-deriving-from-the-backgroundservice-base-class

How to implement .NET code library as a service layer - sharing same BL/CRUD between several applications

Setting: I'm developing an intranet tool set for my department, the main point of which is to centrally manage data quality and accessibility, but also to automate and scale some partial-processes.
Problem: I currently have my business logic in a CLR assembly, which is available on my SQL-Server for other CLR assemblies that run automated ETL directly on the SQL-Server. I am also developing an intranet site, which also needs the code information in that business logic assembly, but referencing the CLR assembly code has been working out sub-optimally, in terms of deployment and code maintenance. Also another department has voiced interest in using the code-base and data for their own intranet site.
Question(s): I've read quite a few Q&A(1,2,3,4,...) on SO to this topic, but I find it a very encompassing, so I'll try to ask questions for a more specific case(i.e. a single BL and Data Access code base)
Is a WCF service the solution I want? All my potential service clients run on the same server, is there maybe another way to reference the same code base both in CLR assembly and website projects? I don't need support for different platforms(ex. Java) - everything is .NET(yay for in-house progr!) - is WCF overkill?
Can code from a WCF service be used like a class library, or do I need to program a new way for accessing classes/methods from the service?
Separation of Development, Test and Productive instances?
Can a WCF service be updated while clients are accessing it, or do I need to schedule maintenance windows? When I update the service, do I need to update the client as well in some way?
Can I dynamically set the service reference, like I currently am dynamically setting the database connection string, depending on if StageConfig = dev, test, or prod?
My CLR assemblies are written for .Net 3.5, but the websites for .NET 4.0, will that pose a problem?
What minimum set of .NET service architecture programming do I need to know to accomplish this? I'll learn more about WCF with time, but I need to evaluate architecting effort and weigh it against getting things done(feature requests). Does the MS tutorial get me the desired skill?
I appreciate answers to only single questions, if you feel you know something, I'll +1 whatever helps me get closer to a complete answer.
OK, so you want to make your code enterprise-wide. There are two fundamental problems to talk about when you want to do this, so I'll structure the answer that way:
You have to understand what WCF is all about.
You have to manage your dependencies correctly.
What WCF is about
WCF is a way of doing RPC/RMI (Remote procedure call/remote method invocation) which means that some client code can call code that is located somewhere else through the network.
A callable WCF service is determined by the ABC triplet:
The service specification is implemented as a .NET interface with a "ServiceContract" attribute. This is the Contract ("C")
The "location" of the service is determined by a pair : Address ("A") and Binding ("B"). The Binding determines the protocol suite to be used for communication between client and server (NetPipe, TCP, HTTP, ...). The Address is a URI following the scheme determined by the Binding ("net.pipe", "net.tcp", "http", ...)
When the client code calls a WCF service at a specific Address, with a specfic Binding, and a specific Contract (which must match what the server at the specific Address and the specific Binding is delivering), WCF generates a proxy object implementing the interface of the contract.
The program delivering the service is any .NET executable. It has to generate one or many WCF Hosts, that will register objects or classes that implement the service contract, and asociate each delivered service to a specific Address and Binding. (possibly many thereof)
The configuration can be through the app .config file, in which you will be specifying ABC triplets and assotiate these triplets with a name that you will use in your application. You can also do it programmatically, which is very easy.
WCF does not address your problem of deploying your application, or the configuration of addresses and binding. It just addresses the problem of letting two executables communicate with each other with strongly-typed objects (through a specific interface). Sharing the service configuration is up to you. You may use a shared .config file on a Windows share, or even set up a LDAP server that will deliver all the data you need to find your service (namely A and B).
Managing your dependencies correctly
In your scenario, there are three actors that want to use your WCF infrastructure:
Your SQLCLR assembly, which will be a client.
The intranet site, which will be another client.
The service host, which will be a server.
The bare minimum number of assemblies will be 4. One for each of the aforementioned actors, and one specifying the contract, which will be used by all three actors. It should contain the following things:
The interface specifying the contract.
All types needed by the interface, which will of course be sent through the network, and therefore must be serializable.
There should be nothing more in it, or else, it will be a maintenance nightmare.
Answer to your questions
I hope that my answer is clear. Let's sum up the answers to your questions.
Is a WCF service the solution I want? All my potential service clients
run on the same server, is there maybe another way to reference the
same code base both in CLR assembly and website projects? I don't need
support for different platforms(ex. Java) - everything is .NET(yay for
in-house progr!) - is WCF overkill?
Everything is overkill. WCF is rather easy to use and scales down very well.
Can code from a WCF service be used like a class library, or do I need
to program a new way for accessing classes/methods from the service?
Setting up a WCF on existing code requires only the implementation of an additional class, and some code creating the Hosts which will serve the aforementioned class.
Calling a WCF service requires the creation of a Channel, which is a .NET (proxy) object implementing the interface.
So basically, your business code remains in the same state.
Separation of Development, Test and Productive instances?
WCF does not take care of that. Different environments, different service addresses. You have to take care of this yourself.
Can a WCF service be updated while clients are accessing it, or do I need to schedule maintenance windows?
It depends on your maintenance policy. Kill the serving process and launch the new version is the basic upgrade mechanism.
When I update the service, do I need to update the client as well in some way?
Provided that you manage your dependencies correctly like I sketched in the previous section, you need to update the clients only if the service specification (the interface) changes.
Can I dynamically set the service reference, like I currently am dynamically setting the database connection string, depending on if StageConfig = dev, test, or prod?
You have to manage that, probably by etting Address and Binding for a service programmatically.
My CLR assemblies are written for .Net 3.5, but the websites for .NET 4.0, will that pose a problem?
Provided that you manage your dependencies correctly like I sketched in the previous section, the only constraint will be the minimum CLR version required by the "contract" assembly.
What minimum set of .NET service architecture programming do I need to know to accomplish this? I'll learn more about WCF with time, but I need to evaluate architecting effort and weigh it against getting things done(feature requests). Does the MS tutorial get me the desired skill?
You'll need the result of these exercises:
Make two executables, a client and a server, that will communicate
through a WCF contract located in a separate DLL. The configuration
should be located in the app .config file.
Make two executables, a client and a server, that will communicate
through a WCF contract
located in a separate DLL. The configuration should be determined programatically.
Try to send a serializable class as a parameter to your service.
Try to send a serializable class as a return value of your service.
After that, you'll need to think about the best/cheapest way to share the Addresses and Bindings of your services.
Hope it helps.

WCF as BLL (Middle Tier) and Security techniques

So bear with me, i am new at MVC and WCF. I already have a set of services (WCF) that exposes my BLL and I am trying to consume those from my MVC.net web application but i am unsure on how to perform security operations here.
These are my app requirements:
Be able to consume WCF services using different credentials for every user on the web application
My BLL (WCF) needs to know what consumer is calling it (right now I only have the MVC app but i am planning to add iOS and Andriod calls to it, so later on i will add REST services to the WCF endpoints) Is there any design pattern for this out there? (or should i just use the soap header to include the caller ID? should i use some sort of caller secret or something?)
I need a security mechanism like Tokens or something so I dont have to pass the username and password on every call of the service method (WCF)
What i have so far:
WCF uses a certificate and and with a custom username validator.
I have manually coded proxies using the contract interfaces instead of generated proxies: But I hate the fact that i have to validate username and password every time a call is made to a WCF service. How in heaven can i use Tokens here? like to know if a given token sent on the soap header is valid or not yet expired? i have searched a lot and no tutorial/code/example is clear enough for me to actually start coding that ;(
I am trying to cache the ChannelFactory but should I? i mean, i will need to cache a channer factory per logged in user per contract ;( is that ok? what can i do here?
Thanks in advance!
Should you cache the ChannelFactory per user per contract?
It depends. There are a couple of considerations. Instantiating a channel factory could take up to 70ms. If you are doing this repeatedly, you will see a noticeable performance hit if you are not caching the ChannelFactory and instantiating one (or more) each time a user makes a http request to your MVC app that results in controller actions calling web services. This would indicate that caching the channelFactory would be beneficial for speed.
On the other hand, depending on the number of users you have, if you are caching a lot of channel factories (in a static dictionary for example), you are going to start to use a non-trivial amount of memory - this may become an issue for you.
You have to decide if the cost of instantiating channel factories on the fly (and correctly closing / aborting them and their contained channels) is too high a price vs increasing memory utilisation in the application pool hosting your MVC app.
Either way, I strongly advise to profile your app before you deploy to production.

store data inside WCF service and extract it later by the client

i have an Autocomplete ajax control that calls a WCF service method automatically.
this method gets a string as an input parameter and return a list of strings.
i don't make that call from the client , the control does it, but i write the content of this method.
Can i store some data somewhere in the WCF service when that method is called and extract it later when i use the WCF from the client ?
i mean , i want the control to call the method, in the method i'll store some data and later when i use the WCF client object i'll extract it.
is there such "WCF cache" mechanism?
No, there's no such thing as a 'WCF cache' mechanism. But WCF is .NET, and in a .NET application you can use the Caching Application Block.
Caching has very little if anything to do with WCF. You cache inside your application, but the caching mechanism for a WCF service is fundamentally the same as a Windows Forms application or a managed Windows Service (or an ASMX webservice, or a ASP.NET application, or any .NET application). The only difference is how you use and rely on the cache & how the applicaton's lifecycle is managed.
If your WCF service is hosted in IIS (as is very popular), then when the application pool is recycled (or the website is restarted) you will lose everything in the cache. Will this be a problem?
The typical use case for a cache is when you have a set of data stored (in, say, a database) that will need to retrieved over and over again. Rather than get from the database everytime, you get from the cache. If it's not in the cache, you get from the database and put it in the cache so it's there for next time. It sounds like you want to store some data from the client application in the cache. You can do this, but what will happen if it's not there when you go to retrieve it.

Sharing session between WCF services

I have been working on splitting up the app tier and web tier of a web application. In the app tier, I managed to separate the business logic into a bunch of services exposed using WCF proxies. The problem is that these services talk to another legacy application that uses a large CLR object as its primary means of communication. To keep things quick, I had been keeping a copy of this object in the session after I created it the first time. Now I know that WCF can do sessions, but the session storage is per service whereas my business logic is now split into multiple services (as it should be).
Now the questions:
Is there a way to share session storage between WCF services hosted on the same host?
Is this even something I should be doing?
If not, then what are the best practices here?
This is probably not the first time somebody’s had a large business object on the server. Unfortunately for me, I really do need to cache this object per user (hence the session).
It’s possible the answer is obvious and I'm just not seeing it. Help please!
I think instance context sharing can help
http://msdn.microsoft.com/en-us/library/aa354514.aspx
As far as I understand WCF, it is designed to be as stateless as it could be. In a session you can remember some values in your service, but objects are not meant to live outside the scope of a session.
Therefore, I'd think you are in trouble.
Of course, there might be some way to store and exchange objects between sessions that I don't know (I use WCF, but I don't know very much about it, apart from what I need for myself).
(if there is a way to share objects between services, it probably would only work on services you host yourself. IIS hosting might recycle your service sometimes)
Perhaps you can wrap this object in a singleton service. This is a service with only one instance, which will not be destroyed between calls. Because you need an object for each user, this service has to manage a list of them and the calling services has to provide the needed authentication data (or sessionid). Don't forget a timeout to get rid of unneeded objects...
Create a facade service which hosts the large CLR object on behalf of the other app tier services. It can work as an adapter, allowing more specific session identifiers to the more advanced app tier services you have created. The facade can provide a session identifier, like a GUID, which your app tier services can use to get re-connected with the large CLR object.
This provides a few advantages:
Some of your app tier might not need to know about the CLR object at all. They only communicate with the remote facade.
the 'large CLR object' host retains the session object on behalf of the other services who can now share it.
The app tiers now have a facade through which they talk to the legacy service. As you work to refactor this legacy service, the app tier doesn't have to change.
Depending on your setup, you may be able to host the facade via in proc hosting which will give retain performance boost you are seeking.
Breaking things up into subservices seems like a good idea if you want to be able to spread the app out over a farm. However, it's important to keep in mind that whenever an object crosses the appdomain boundary at the vary least it will have to be copied in memory.
It all depends on how big the object is and what kind of data it holds.
If you don't want to pass the object because it's too large you may want to make a query API for the service which receives it. In this way you could manipulate that object without having to do expensive serialization or remoting.
Keep it simple. Since you already have access to Session in your WCF, you can use the SessionID from there. Now:
Create a static dictionary somewhere, where the Key is your sessionId and the value is the business object you want to store.
Instead of accessing the business object in session, just access the sessionid and get the business object from the Value of your dictionary.
(You can also use some type of caching if you wish, for example System.Web.Caching, that way you don't have to cleanup the dictionary manually)