Caching ASP.NET users related data within WCF service - asp.net

My requirement is to call WCF web service from ASP.NET code behind and pass some data for example:
void Add(int x, int y);
Result of the operation should be somehow stored within WCF web service (member variable).
Later user should be able to call
double Equals();
and get the result of the operation. Of course since it's an open website many non-authenticated users can open the ASP.NET page and call the web service.
Alternatively Add method can return "key" that can be used to get result back, for example :
Guid Add(int x, int y);
double Equals(Guid key);
I don't think I can use WCF sessions since web service will think that there is only 1 client ( WebSite calling the webserivce hosted in IIS ).
Users are not authenticated - they are anonymous users.
I could use : ( please take a look at my EDIT )
InstanceContextMode =InstanceContextMode.Single
as attribute over my web service and store Dictionary<key, result> but the problem is when can I remove entry from Dictionary? Should I use some sort of BackgroundWorker to check dictionary every e.g. 15 minutes and remove old entries? In that case I would have to store DateTime against each entry but that's not a problem if this is the best way to implement this solution...
My example Add/Equals methods are only to illustrate the problem, real requirement need to store much more data per user than simple double result
Thanks in advance for all the help.
EDIT:
After thinking more about the InstanceContextMode =InstanceContextMode.Single I think it's not the best option to use with ASP.NET since if 100 users will call the web service at the same time I will get 100 sequential invocations which will cause performance issues.
In that case do you have any ideas how to implement this without changing InstanceContextMode setting (which by default is PerSession as far as I know) ?

I think,Keeping the
InstanceContextMode =InstanceContextMode.Single
as the service behavior, if your architecture permits, you can use the System.Web.Caching.Cache object implemented in a static class(so that it will be instantiated only once) ,where you can specify the cache dependency/expiration time etc and hence you can get the complete set of functionalities offered from the cache service, instead of implementing on your own.
Edit:
If your primary intention is about Caching, then you need not use the Instance Context mode even. You can simply implement your own static Cache provider based on the System.Web.Caching.Cache and pass the cacheKey as shown in the following sample:
public int Add(int a, int b)
{
string cacheKey = a.ToString()+b.ToString();
if (!CacheProvider.Contains(cacheKey))
{
CacheProvider.Add(cacheKey, a + b);
return a + b;
}
else
{
return (int)CacheProvider.GetValue(cacheKey);
}
}
CacheProvider in the above code is the static implementation of your Cache provider.

Related

in-memory cache for ASP.NET web app

I need to cache a very small amount of data for a maximum of one hour for an ASP.NET web application (one instance). Obviously this needs to be thread-safe so I can access the cache from within my requests.
I want to do this "in process", and not use anything external.
What would be the easiest way to implement this?
You can user the Cache object ASP.NET provides you with.
You can create a property that returns the cached object if exist else retrieve it from db.
private myClass myProp {
get{
if (Cache["Key1"] == null)
Cache.Add("Key1", "Value 1", null, DateTime.Now.AddMinutes(60), Cache.NoSlidingExpiration, CacheItemPriority.High);
return (myClass)Cache["Key1"];
}
}
Use static variables. You could write a static cache class including your update logic (maximum of one hour) and store the retrieved data in a static member.
The class will persist in the app pool until it is recycled. This could be too often or too rarely for your use cases. But the caching ability should be fair enough.
For the thread-safety issues you could provide getter methods in this class and make use of the lock statement.

Autofac Multi-tenant IoC Container in an ASP.NET Web API Application

Autofac 3.0 will have a MultitenantIntegration support and its preview release is out now. To try it out, I created an ASP.NET Web API application with the following configuration:
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {
var config = GlobalConfiguration.Configuration;
config.Routes.MapHttpRoute("Default", "api/{controller}");
RegisterDependencies(config);
}
public void RegisterDependencies(HttpConfiguration config) {
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// creates a logger instance per tenant
builder.RegisterType<LoggerService>().As<ILoggerService>().InstancePerTenant();
var mtc = new MultitenantContainer(
new RequestParameterTenantIdentificationStrategy("tenant"),
builder.Build());
config.DependencyResolver = new AutofacWebApiDependencyResolver(mtc);
}
}
It gets the job done and creates a LoggerService instance as ILoggerService per tenant. I have two problems at this stage which I wasn't able to solve:
I used out of the box provided RequestParameterTenantIdentificationStrategy here as the TenantIdentificationStrategy just for this demo application. I am able to create my custom TenantIdentificationStrategy by implementing ITenantIdentificationStrategy interface. However, TryIdentifyTenant method of the ITenantIdentificationStrategy makes you rely on a static instance such as HttpContext.Current which is something that I don't want in an ASP.NET Web API environment as I want my API to be hosting agnostic (I know that I can delegate this work to the hosting layer but I would rather not to). Is there another way to achieve this in a way that I won't rely on a static instance?
I also have a chance to register tenant specific instance as below:
mtc.ConfigureTenant("tenant1", cb => cb.RegisterType<Foo>()
.As<IFoo>().InstancePerApiRequest());
However, one of my situations requires me to pass the tenant name through the constructor parameter and I would love to have something like below:
mtc.ConfigureTenant((cb, tenantName) => cb.RegisterType<Foo>()
.As<IFoo>()
.WithParameter("tenantName", tenantName)
.InstancePerApiRequest());
Currently there is no such an API. Is there another way to achieve this or this kind of requirement doesn't make any sense?
Multitenant support has been available for a long time, it's just that 3.0 is the first time we've had a NuGet package for it. :)
The RequestParameterTenantIdentificationStrategy is, as documented, just a very simple example showing one possible (and not recommended) way to identify tenant. You will have to choose for yourself how to identify your tenant based on the operating context. It could be from a web.config value, an environment variable, or some other thing in the current environment. If you don't want to use HttpContext.Current, don't. It's up to you to pick where you get that info from.
(A note on the RPTIStrategy - the part that isn't recommended is using a querystring or request parameter as the tenant ID mechanism. I use HttpContext in my production apps and it works fine. There's only so much you can abstract out before you have to actually touch the bare metal.)
There is no way out of the box to provide the lambda registration syntax you're asking for, primarily because tenant is not passed through the resolution process. The resolution process is:
Identify the tenant with the strategy.
Find the tenant's configured lifetime scope.
Use standard Autofac Resolve style syntax.
It's intentionally simple and analogous to the existing operations. At the time of resolve, the sub-lifetime-scope belonging to the tenant is tagged with the tenant ID but the resolution operation doesn't know about the tenant ID... so the lambda wouldn't work (and probably won't anytime soon because it'd change the fundamental internals of the way Autofac works if it did).
To accomplish what you're looking for, you can use a combination of the InstancePerTenant extension when registering...
var builder = new ContainerBuilder();
builder.RegisterType<Foo>().As<IFoo>().InstancePerTenant();
...and registering the ITenantIdentificationStrategy as a dependency in your container.
builder.Register(myIdStrategy).As<ITenantIdentificationStrategy>();
Then make your class take an ITenantIdentificationStrategy rather than the tenant ID directly. Use the strategy to get the tenant ID instead.
If you REALLY want to get fancy, you could register a keyed lambda that resolves the ID strategy, then gets the tenant ID. Then you could add a parameter registration to the object like you did but using a keyed service. (I'm going to go by memory now, so you'll have to double-check my syntax here, but it'll be something like this...)
builder.Register(c =>
{ var s = c.Resolve<ITenantIdentificationStrategy>();
object id;
s.TryIdentifyTenant(out id);
return id;
}).Keyed<object>("tenantId");
builder.RegisterType<Foo>()
.As<IFoo>()
.WithParameter(
(pi, c) => pi.Name == "tenantId",
(pi, c) => c.ResolveKeyed<object>("tenantId"))
.InstancePerApiRequest();
Again, you'll want to double-check me on that, but I'm pretty sure that (or a minor variation) should work to get you what you want.

Best Way to Write an Asp.Net Web Service To Play Well In the Wild

I am writing an API for my ASP.NET application that other developers will use. The API will basically return a list of people with their first name, last name, and id. There are lots of ways to write web services in ASP.NET, the easiest probably being create a web service function (asmx) that returns a DataTable. This is simple enough for other .NET developers to deal with, but I am not convinced that this is the best way to write a web service for general platform and language independence.
What is the currently accepted standard to write a web service like this that plays well in the wild today?
Some ideas that come to mind from experience:
Use WCF, not .asmx. WCF does all the same things that ASMX files do, and is generally the replacement for ASMX services (see here and here).
Write methods using simple POCO data types, like List<Person> rather than DataTable. Basic types serialize more easily and will make more sense in other programming environments since you want your service to be language independent.
Provide generic CRUD methods for managing data. Depending on how your service will be consumed, if the user needs to modify data, a simple method is to provide getBlah(), updateBlah(obj newObj), deleteBlah(obj objToDelete), etc. that use the same data types.
Hide the details that the service consumer doesn't need to know, rather than just blindly exposing all of your data types, structures, and field names as-is. This will make your service more robust for handling internal changes, and you can simplify and control what the end-users see. For instance, if you have a Person class with 30 properties, and only 5 are relevant to the end-user, provide a class that interfaces between Person and a PersonSimple class which is exposed. Without this layer, your end-users will have to modify your code every time you change your data structure, and you will be locked down by this tight coupling.
If security is important
Execute your service over SSL. This protects data transfered over the wire from being sniffed.
Use authentication, either with a Login method and session, or SOAP headers. Services by default are anonymous unless there is some sort of authentication scheme. Even if you think nobody will find your service because you only provide the URL to your users, it will get out somehow, somewhere, and people will try to misuse the service when it does. Plus, you can control who can do what by different logins and authorization schemes.
I am currently working on a similar issue: A web api service in .NET that receives data tables as input parameters, apply some operations on them (using Table Valued Functions), and return some output data tables.
In your case, you don't need to use a complex class like DataTable; you could use an array (List<>) of a simple class with fields like first name, last name and id. Using Web Api of ASP.NET you could do something like the following:
1) Create a new WebApi project in Visual Studio: For example (in VS 2012) C# > Web > ASP.NET MVC 4 Web Application > select "Wep Api" as project template
You will see a VS project with lots of folders, including one named Models
For help see: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
2) Create a new model code file Person.cs with a class like the following:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string[] Friends { get; set; }
}
3) Create e new controller code file PersonController.cs with methods for getting, inserting and updating records of the database. All the necessary serialization/deserialization (JSON and XML) and data binding is done automatically by the Web Api environment set by the project template.
// Get all the records of persons
public IList<Person> Get()
{
// read database into a list of persons (List<Person>)
// return List<Person>
}
Return record of a selected person:
public Person Get(int id)
{
// read database for a selected person
}
Parameter binding (reading a JSON/XML content sent by http POST into an object, or into a list objects) is also done automatically, as easy as the following:
// parameter binding: Create a Person object with content from XML/JSON
public void ReadPerson(Person p)
{
Trace.WriteLine(Person.Id);
}
public void ReadPersonList(List<Person> plist)
{
Trace.WriteLine(plist.Count);
}

Creating Global Variable For Web Application - ASP.NET

i'm building my web application to connect with db.
so far i have managed to deal with it, (although i didn't build BLL & DAL).
i have a table which has column "id". i know there is a way to declare it in the SQL Server to be incremented automatically. ( but i don't want it).
i want to declare a global application variable that will hold the value.
i have 2 questions:
how i declare it?
where i create it and initialize it ? (i have several login pages).
THANKS!
p.s
it would be helpful if someone will tell me how do i build the DAL with my stored procedures?
and for what i need yo use BLL which i cant do in the DAL?
You can use the Application object - it is part of the HttpContext and is directly accessible on any page.
If you don't want to use it, you may want to write a Globals class (or whatever name you like) that holds static members.
public class Globals
{
public static int Counter { get; set;}
}
// accessed from other classes:
Globals.Counter++;
Either approach will not work of you have a web farm or several web applications and will not survive restarts.
Regardless of these options, the right solution (even if you don't want to use it - can you explain why?), is to use the ID field with the IDENTITY clause.
Storing the variable is the easy part. Managing your own ID generation and the contention and concurrency issues is the hard part. Good luck.
There really is no such thing as a global variable in ASP.NET. Remember, HTTP is stateless.
The closest you can come is storing something in the Application object:
Application["myvar" ] = x;
x = Application["myvar"];
But even here, this variable is lost when the app needs to restart, which it can do from time to time.
A much better solution for what you describe is a database value.
Incrementing an integer and then throwing that incremented ID into the db is fraught with danger. Multithreading? What happens when the application bounces? Do dev and prod deployments share the same set of numbers?
It sounds like you need a globally unique identifier and can be created outside of the database. That sounds like a job for a GUID. Sure, it takes up more space in the db, but it probably isn't the worst thing you are going to do to the database.

Need to store a static value for the duration of a request. How?

I have an ASP.NET MVC application. I have come to an idea of generating autoincremented values to be used as unique element ids. The question is, how can I have and work with a global variable which should be there for the duration of a request (page generation) but no longer?
I thought of using TempData for this shared variable and then just delete this key when the page is done. But then, where in code to purge this TempData key? Obviously it has to be some very last piece of code where the page has been rendered already.
Any input is highly appreciated.
EDIT: I have a number of HTML helpers that can be called from various views and partial views, so declaring a variable on a page and passing it to each helper is obviously not a good solution. I wish to just use the helpers and know they all are getting unique ids behind the scenes.
Okay, I have googled a little bit and found a solution on ASP.NET forums.
http://forums.asp.net/t/1401685.aspx
Obviously, I can use the HttpContext.Current.Items collection to have my little static variable for the duration of a request.
If all you need is to store a number, the resources that would take to manage its lifestyle would take a lot more than just having a one static integer and always reusing it.
Do not bother deleting the key after each request. Just use a static (I think this is shared in visual basic) integer, use and increment it every time you need a unique value. Also take its mod with a ridiculously high number each time to make sure it will not be reused in a single request and it will never overflow.
Why don't you define your integer variable at the top of the page view file?
Use it throughout the view rendering execution and at the end of it you can easily leave it as is. You don't have to explicitly destroy anything. Your variables live for the duration of request only. IIS is stateless service (if you subtract Session, Cache and Application variables) so it doesn't really remember anything explicitly.
I would imagine you could use the Application_BeginRequest and Application_EndRequest methods in global.asax.cs; Note I can't double check the method names currently, but I think they are close.
You could create a member variable in your controller which would be regenerated for each request:
public class ItemController : Controller
{
private int _UniqueID = 0;
public ActionResult Index()
{
foreach (var item in items)
{
item.UniqueID = _UniqueID++;
}
// etc...
}

Resources