Properly using C# lock in web application - asp.net-mvc

I have a helper class which reads a big XML document and generates a list of c# objects.
I work with these objects quite a lot, so i thought the best way of doing this would be to save them in memory and then access them from there.
I made a simple repository, which gets an object from memory, and if doesn't exists, it adds it.
The Repository looks like this:
public class XmlDocumentRepository
{
private readonly ICacheStorage _cacheStorage;
public XmlDocumentRepository(ICacheStorage cacheStorage)
{
_cacheStorage = cacheStorage;
}
private readonly object _locker = new object();
private void DeserializeXmlDocument()
{
lock (_locker)
{
// I deserialize the xml document, i generate the c# classes, and save them in cache
IEnumerable<Page> pages = new XmlDeserializerHelper().DeserializeXml();
foreach(var page in pages)
{
_cacheStorage.Add(page_Id, page);
}
}
}
public Page GetPage(Guid page_Id)
{
Page page = _cacheStorage.Get<Page>(page_Id);
if (page != null)
return page;
lock (_locker)
{
page = _cacheStorage.Get<Page>(page_Id);
if (page != null)
return page;
DeserializeXmlDocument();
page = _cacheStorage.Get<Page>(page_Id);
return page;
}
}
}
The XmlDocumentRepository is used inside a web application (asp.net mvc more exacly).
Is the implementation of the repository good? I am using the lock statements properly?

In my comments on the question I misunderstood the cache being shared. I think you will need to do one of the following options:
Make XmlDocumentRepository a singleton which is used across all requests because the lock object is a private field so each request will have a new instance of the repository with a new field.
Make the lock object a static field so that it is shared across all XmlDocumentRepository instances.

As a primary rule, you want to protect all access variations to data stores that are used by multiple threads. I see several potential problems with your implementation;
1: ICacheStorage is provided from the outside, which means that this collection could be modified elsewhere, which may or may not be protected by locks. Maybe you should require that the collection itself uses locking internally, or other types of thread safety mechanisms?
2: You have inconsistent lock protection of data access. In GetPage you access _cacheStorage before applying the lock, while in Deserialize, you access it inside a lock. This means that you may get a result where one is adding to the cache while another is getting from it.
3: Do you require thread safety for the cache, for xml reading, or both?
If you only need to protect the cache, move reading of xml outside the lock. If protecting both, you should put the entire GetPage function inside the lock.

Related

Safely re-initialize "single instance" dependency in a DI Container

I have a widely used cache interface in a web application with the implementation currently registered as SingleInstance.
This current cache implementation assumes single threaded initialization, but once initialized is immutable, so is safely shared across multiple threads.
However, this means that currently, if the underlying values change, the cache doesn't get updated until the application is restarted. While updating the underlying values is rare, we would now like to provide application behavior that modifies the underlying values, and then tells the cache to refresh.
I could modify the cache implementation to use locking, or perhaps utilize one of the .NET concurrent collections to safely update the cache values.
However, I'm wondering if autofac provides a capability that would allow me to change out the registered instance for a new instance on the next request, so that the cache implementation itself would not need to be modified.
So the ideal behavior would be, that when we modify the underlying values, we trigger the creation of a new cache instance. Once the instance is finished initializing, all in-progress requests continue with the old cache instance, any new http request scopes resolve to the updated instance.
Does autofac provide a built-in way to support this scenario?
You can never safely replace a singleton registered instance in your container. Once other singleton components depend on that, they will simply hold a reference to the old instance, and replacing the instance in the container means that some components (that will be created after the replace action) will refer to the new instance, while other components keep referring to the old instance. This will hardly ever lead to the behavior you like, and will most likely cause bugs.
My advice is never try to change your container's registrations, once the application is running. This will very quickly become quite complex to oversee whether the situation is correct and is thread-safe. For instance, what if you replace the instance at the time that the object graph for another thread is being resolved? It could mean that that object graph holds both a reference to the old and the new instance.
Instead, solve this problem at the application level. First of all, you need two APIs; one for reading the cache, and a second for updating the cache. Both can be implemented using the same component though:
// Very simplified version of what you actually might need
interface ICache { CacheObject Get(); }
interface ICacheUpdater { void Set(CacheObject o); }
A simplistic implementation could look like this:
sealed class Cache : ICache, ICacheUpdater
{
private static CacheObject instance;
public void Set(CacheObject o) => instance = o;
public CacheObject Get() => instance;
}
This implementation might work, but if the cache is retrieved multiple times within the same request, it's possible to read both the old and the new values within the same request (since a different thread can call Set in between). This might be a problem. In that case, you can change the implementation to the following:
sealed class HttpCache : ICache, ICacheUpdater
{
private static readonly object key = typeof(HttpCache);
private static CacheObject instance;
private static IDictionary items => HttpContext.Current.Items;
public void Set(CacheObject o) => instance = o;
public CacheObject Get() => (CacheObject)items[key] ?? (items[key] = instance);
}
In this implementation an extra reference to the cache object is stored in the HttpContext.Items dictionary. This ensures that during the execution of a single (web) request, always the same instance is retrieved.
This example assumes you are running a web application, but you can easily imagine a solution for a different application type.
To update a component registered as a single instance, you can have a registration like this :
builder.RegisterType<ServiceProvider>().SingleInstance();
builder.Register(c => c.Resolve<ServiceProvider>().Service).As<IService>();
and ServiceProvider like this :
public class ServiceProvider
{
public ServiceProvider()
{
this.Service = new Service();
}
public IService Service { get; set; }
}
To update the instance you only have to do that :
container.Resolve<ServiceProvider>().Service = newInstance;
The second part of the question may be more difficult :
Once the instance is finished initializing, all in-progress requests continue with the old cache instance, any new http request scopes resolve to the updated instance.
What you want is to inject a single instance registration in a specific scope. To make this, you can use the ChildLifetimeScopeBeginning event to set the instance for the whole life of scope.
builder.RegisterType<ServiceProvider>().Named<ServiceProvider>("root").SingleInstance();
builder.RegisterType<ServiceProvider>().InstancePerRequest();
builder.Register(c => c.Resolve<ServiceProvider>().Service).As<IService>();
IContainer container = builder.Build();
container.ChildLifetimeScopeBeginning += (sender, e) =>
{
ServiceProvider scopeServiceProvider = e.LifetimeScope.Resolve<ServiceProvider>();
ServiceProvider rootServiceProvider = container.ResolveNamed<ServiceProvider>("root");
scopeServiceProvider.Service = rootServiceProvider.Service;
};
To change the global IService instance you will have to resolve the "root" named ServiceProvider
scope.ResolveNamed<ServiceProvider>("root").Service = newInstance;
and to change the scope only IService instance you will resolve a normal ServiceProvider
scope.Resolve<ServiceProvider>().Service = newInstance;

MVC5 keep object in all functions

This question might sound dumb, but I am new to asp.net mvc and can't find the answer to my question.
In my application ( a game) I have a model of the game GameModel (it contains a multidimensional array). What I want is to be able to use the same object in every controller I use. So I create it once and after that use it in every controller function.
Basically there is one view, and all other functions in the controller edit the object with functions of the model.
My idea was put the object in a session variable, make a function to check the session variable if the object is not set set the object. But this does not look logic to me, hopefully someone has a better solution.
According to your question, you want to keep track of a user's data (game data).
Storing GameModel in Session variable make sense for that scenario.
If you see yourself calling that Session variable from a lot of places, you can create a BaseController and keep it there. Then inherit all controllers from it.
For example,
public class BaseController : Controller
{
public GameModel CurrentGameModel
{
get
{
var model = Session["GameModel"] as GameModel;
if (model == null)
{
model = new GameModel();
Session["GameModel"] = model;
}
return model;
}
set { Session["GameModel"] = value; }
}
}
public class HomeController : BaseController
{
}
Note: You have to keep in mind that if Application Pool recycles or Application crashes, all data stored in Session variable will be lost.
If you want to persist data, you need to store in persistent storage like database.
I don't understand why you don't think Session looks good. It's purpose is exactly keeping data per user througout multiple requests.
You could also return the state of the game to the client using hidden fields. That would be even better than Session, given that your game state doesn't change in the server, as a response to someone else's action.
And finally you can use a static property of a class. Static properties in ASP.NET are kept alive througout the application lifecicle and are visible equally to all users. Meaning, if a user writes something there, another user can read it. You can allocate data per user using a Dictionary<>, though, where the key is the user Id.

Is it legal to extend an entity model with functionality in ASP.NET MVC

first of all here is my situation. I am programming an intranet application using ASP.NET MVC 3 with Entity Framework 4.1. My application has been developed using the "Unit of Work" and "Repository" design patterns.
How ever in my opinion it should go the way that my application has an unit of work that provides a central access to all the repositories which further provide access to the entities.
Lets say I have a entity called "ProductApprovalDocument" with the properties "id", "creationDate" and "approvalDecission" stored in the database. Now I want the user to be able to access a PDF file of the document thats shortly described by the entity. Because the files are stored in a central directory on a file server using the URL format "[fileServerDirectoryPath]/[ProductApprovalDocument.id].pdf", I do not want to save an extra property for that filepath on the database. What I would like to do, is give the entity an extra property called "filepath" that automatically constructs the path with the given information and returns it.
Now the Problem:
I use an interface called FileService to abstract file access from the rest of the application. Now in my case I would have to access the UnitOfWork object out of the entity model, to retrieve the current FileService implementetion and get the preconfigured filepath. I think that's the totaly wrong way because to me an entity model should only be used as a data container not more or less.
Now the Question:
How do I handle such a situation. I would not like to always set the filepath property through the controller because ist more or less static and therefore could be done somehow automatic by the model.
Edit (final solution):
Thanks to the answer of Andre Loker I gained another point of view to my problem.
What was the central target I wanted to reach?
I wanted the user to gain access to a file stored on a fileserver.
Do I have to provide every displayed entity with the total filepath?
No! Think about the principle of MVC! User actions get processed by the controller just in time. You don't have to provide information untill it really get's used.
So the solution is just to render all data as usual but instead of displaying a static html link to the files, you have to include an ActionLink to the Controller which calculates the filepath on the fly and automatically redirects the user to the file.
In the View do this:
#Html.ActionLink(Model.ID.ToString(), "ShowProductApprovalDocumentFile", "ProductApprovalDocument", new { ProductApprovalDocumentID = Model.ID }, null)
instead of this:
#Model.ID
And add an corresponding Action to the controller:
public ActionResult ShowProductApprovalDocumentFile(int ProductApprovalDocumentID )
{
return Redirect(_unitOfWork.FileService.GetFilePathForProductApprovalDocument(ProductApprovalDocumentID));
}
Thanks to the guys that took the time to give me an answer and special thanks to Andre who lead me to the satisfying answer! :)
If I understand the property correctly, there are several options:
1) Make the FilePath property use a service locator to find the FileService:
public string FilePath {
get {
FileService fileService = DependencyResolver.Current.GetService<FileService>();
return fileService.GetFilePathForDocument(this);
}
}
While I'm not a hugh fan of static service locators as they make testing more difficult, this could be a viable option. To make it more easily testable you can make the file service locator injectable:
private static readonly Func<FileService> defaultFileServiceLocator = ()=>DependencyResolver.Current.GetService<FileService>():
private Func<FileService> fileServiceLocator = defaultFileServiceLocator;
public Func<FileService> FileServiceLocator {
get { return fileServiceLocator; }
set { fileServiceLocator = value ?? defaultFileServiceLocator; }
}
And then use this in FilePath
public string FilePath {
get {
FileService fileService = fileServiceLocator();
return fileService.GetFilePathForDocument(this);
}
}
This way you can inject your own file service locator during testing.
2) Explicitly require the FileService when retrieving the file path. Instead of a FilePath property you'd have:
public string GetFilePath(FileService service){
service.GetFilePathForDocument(this);
}
The problem with this is of course that now the caller of GetFilePath needs to have a FileService. This isn't much of a problem for controllers, because if you use an IoC you can inject a FileService into the controller constructor. This approach is the cleaner one as it doesn't depend on service locators, but as you see it is slightly more inconvenient for the caller.
3) Inject the FileService into the document class itself.
Instead of using a file service locator you'd inject the file service itself when you construct your ProductApprovalDocument. With this approach you can use a simple FilePath property again. The main problem is that this often doesn't play too well with ORMs, as they often construct the objects using a default constructor and you'd have to somehow hook into the object construction process to inject the dependencies. Also, I'm not a big fan of injection services into domain objects.
4) You set the FilePath from outside the entity. As you said this should be done somewhat automatically as you don't want to do it manually every time. This would require some layer through which all entities need to pass which sets up the FilePath property.
5) Don't make FilePath a property of ProductApprovalDocument at all. This would be a reasonable choice, too. ProductApprovalDocument doesn't know anything about its FilePath, so why should it be a property? Its the FileService that calculates the value. You can still have a distinct view model version of ProductApprovalDocument which does have a FilePath property. You'd set the property when you create your view model:
var model = new ProductApprovalDocumentViewModel();
mapper.Map(realDocument, model); // map common properties with AutoMapper or so
model.FilePath = fileService.GetFilePathForDocument(realDocument);
However, if ProductApprovalDocument needs to do something with its FilePath (why would it?) this approach doesn't work anymore.
Personally I'd go with solution 5, 2 or 1 in that order of precedence, where applicable.
Whilst I would be hesitant to rely on being able to calculate the filepath and I would prefer to store it as part of the entity (in case it ever needs to change for some reason), in your situation if I was adamant I wanted to do it the way you've said, I think I would extend the FileService/ViewModel to have a Filepath property which was derived in the fashion you have stated.
e.g. if I wanted to create a download link I'd do this in the ViewModel
public string FilePath
{
get
{
return String.Format(#"thehardcodedbit{0}.pdf",ID);
}
}
EDIT: If you have an Entity generated by EF4.x then it will have been generated as a partial class so you could always extend it like this (I have done this sort of thing and it works okay):
Say the generated entity looks like this:
Namespace Da_Wolf.Model.Entities.File
{
public partial class UploadedFile
{....}
}
Then you could create a partial class like this:
Namespace Da_Wolf.Model.Entities.File
{
public partial class UploadedFile
{
public string FilePath
{
get
{
return String.Format(#"thehardcodedbit{0}.pdf",ID);
}
}
}
}
Now you have the property you desire available everywhere without adding anything to the ViewModels.

Singletons and ASP.NET MVC

Right now I'm having an issue with a Singleton that I just wrote for use in ASP.NET MVC -- My Singleton looks like this:
public sealed class RequestGenerator : IRequestGenerator
{
// Singleton pattern
private RequestGenerator()
{
requestList = new Stack<Request>();
appSettings = new WebAppSettings();
}
private static volatile RequestGenerator instance = new RequestGenerator();
private static Stack<Request> requestList = new Stack<Request>();
// abstraction layer for accessing web.config
private static IAppSettings appSettings = new WebAppSettings();
// used for "lock"-ing to prevent race conditions
private static object syncRoot = new object();
// public accessor for singleton
public static IRequestGenerator Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new RequestGenerator();
}
}
}
return instance;
}
}
private const string REQUESTID = "RequestID";
// Find functions
private Request FindRequest(string component, string requestId)
private List<Request> FindAllRequests(string component, string requestId)
#region Public Methods required by Interface
// Gets and increments last Request ID from Web.Config, creates new Request, and returns RequestID
public string GetID(string component, string userId)
// Changes state of Request to "submitted"
public void SetID(string component, string requestId)
// Changes state of Request to "success" or "failure" and records result for later output
public void CloseID(string component, string requestId, bool success, string result)
// Verifies that Component has generated a Request of this ID
public bool VerifyID(string component, string requestId)
// Verifies that Component has generated a Request of this ID and is owned by specified UserId
public bool VerifyID(string component, string userId, string requestId)
// Returns State of Request ID (Open, Submitted, etc.)
public Status GetState(string component, string requestId)
// Returns Result String of Success or Failure.
public string GetResult(string component, string requestId)
#endregion
}
And my controller code looks like this:
public ViewResult SomeAction()
{
private IRequestGenerator reqGen = RequestGenerator.Instance;
string requestId = reqGen.GetID(someComponentName, someUserId);
return View(requestId);
}
Everything works okay the first time I hit the controller. "reqGen" is assigned the instance of the Singleton. A new instance of Request is added to the internal list of the Singleton. And then we return a View(). The next time I hit this controller's SomeAction(), I'm expecting the Singleton to contain the List with the instance of SomeClass that I had just added, but instead the List is empty.
What's happened? Has Garbage Collection gobbled up my object? Is there something special I need to consider when implementing the Singleton pattern in ASP.NET MVC?
Thanks!
EDIT: Ahh, the lightbulb just went on. So each new page request takes place in a completely new process! Got it. (my background is in desktop application development, so this is a different paradigm for me...)
EDIT2: Sure, here's some more clarification. My application needed a request number system where something being requested needed a unique ID, but I had no DB available. But it had to be available to every user to log the state of each request. I also realized that it could double as a way to regulate the session, say, if a use double-clicked the request button. A singleton seemed like the way to go, but realizing that each request is in its own process basically eliminates the singleton. And I guess that also eliminates the static class, right?
EDIT3: ok, I've added the actual code that I'm working with (minus the implementation of each Method, for simplicity sake...) I hope this is clearer.
EDIT4: I'm awarding the green check mark to Chris as I'm beginning to realize that an application-level singleton is just like having a Global (and global's are evil, right?) -- All kidding aside, the best option really is to have a DB and SQLite seems like the best fit for now, although I can definitely see myself moving to an Oracle instance in the future. Unfortunately, the best option then would be to use an ORM, but that's another learning curve to climb. bugger.
EDIT5: Last edit, I swear. :-)
So I tried using HttpRuntime.Cache, but was surprised to find that my cache was getting flushed/invalidated constantly and couldn't figure out what was going on. Well, I was getting tripped up by a side-effect of something else I was doing: Writing to "Web.config"
The Answer --> Unbeknownst to me, when "web.config" is altered in anyway, the application is RESTARTED! Yup, everything gets thrown away. My singleton, my cache, everything. Gah. No wonder nothing was working right. Looks like writing back to web.config is generally bad practice which I shall now eschew.
Thanks again to everyone who helped me out with this quandary.
The singleton is specific to the processing instance. A new instance is being generated for each page request. Page requests are generally considered stateless so data from one doesn't just stick around for another.
In order to get this to work at the application level, the instance variable will have to be declared there. See this question for a hint on how to create an application level variable. Note that this would make it available across all requests.. which isn't always what you want.
Of course, if you are trying to implement some type of session state then you might just use session or use some type of caching procedure.
UPDATE
Based on your edits: A static class should not maintain data. It's purpose is to simply group some common methods together, but it shouldn't store data between method calls. A singleton is an altogether different thing in that it is a class that you only want one object to be created for the request.
Neither of those seem to be what you want.
Now, having an application level singleton would be available to the entire application, but that crosses requests and would have to be coded accordingly.
It almost sounds like you are trying to build an in memory data store. You could go down the path of utilizing one of the various caching mechanisms like .NET Page.Cache, MemCache, or Enterprise Library's Caching Application Block.
However, all of those have the problem of getting cleared in the event the worker process hosting the application gets recycled.. Which can happen at the worst times.. And will happen based on random things like memory usage, some timer expired, a certain number of page recompiles, etc.
Instead, I'd highly recommend using some type of persisted storage. Whether that be just xml files that you read/write from or embedding something like SQL Lite into the application. SQL Lite is a very lightweight database that doesn't require installation on the server; you just need the assemblies.
You can use Dependency Injection to control the life of the class. Here's the line you could add in your web.config if you were using Castle Windsor.
<component id="MySingleton" service="IMySingleton, MyInterfaceAssembly"
type="MySingleton, MyImplementationAssembly" lifestyle="Singleton" />
Of course, the topic of wiring up your application to use DI is beyond my answer, but either you're using it and this answer helps you or you can take a peak at the concept and fall in love with it. :)

ASP.NET MVC Session usage

Currently I am using ViewData or TempData for object persistance in my ASP.NET MVC application.
However in a few cases where I am storing objects into ViewData through my base controller class, I am hitting the database on every request (when ViewData["whatever"] == null).
It would be good to persist these into something with a longer lifespan, namely session. Similarly in an order processing pipeline, I don't want things like Order to be saved to the database on creation. I would rather populate the object in memory and then when the order gets to a certain state, save it.
So it would seem that session is the best place for this? Or would you recommend that in the case of order, to retrieve the order from the database on each request, rather than using session?
Thoughts, suggestions appreciated.
Thanks
Ben
Just thought I would share how I am using session in my application. I really like this implementation (Suggestions for Accessing ASP.NET MVC Session[] Data in Controllers and Extension Methods?) of using session as it makes it easy to swap out session for another store or for testing purposes.
Looking at the implementation it reminded me of the ObjectStore I have used in other projects to serialize objects as binary or xml and store in a database or on the filesystem.
I therefore simplified my interface (previously T had to be a class) and came up with the following:
public interface IObjectStore {
void Delete(string key);
T Get<T>(string key);
void Store<T>(string key, T value);
IList<T> GetList<T>(string key);
}
And my session store implementation:
public class SessionStore : IObjectStore
{
public void Delete(string key) {
HttpContext.Current.Session.Remove(key);
}
public T Get<T>(string key) {
return (T)HttpContext.Current.Session[key];
}
public void Store<T>(string key, T value) {
HttpContext.Current.Session[key] = value;
}
public IList<T> GetList<T>(string key) {
throw new NotImplementedException();
}
}
I then take in an IObjectStore in my base controller's constructor and can then use it like so to expose properties to my other controllers:
public string CurrentCustomer {
get {
string currentCustomer =
sessionStore.Get<string>(SessionKeys.CustomerSessionKey);
if (currentCustomer == null) {
currentCustomer = Guid.NewGuid().ToString();
sessionStore.Store<string>(SessionKeys.CustomerSessionKey, currentCustomer);
}
return currentCustomer;
}
}
Am quite pleased with this approach.
I believe this is what Session was designed for - to temporarily store session specific data.
However, due to increased complexity connected with using the Session, even if negligible - in my own ASP.NET MVC project, I have decided to hit the database on every Order creation step page (only ID is passed between the steps). I am ready to optimize and start using session as soon as I will see that the extra database hit for every request is a performance bottleneck.
You can serialize what you wish to persist and place it in a hidden input field like ViewState in WebForms.
Here's an article that should get you started: http://weblogs.asp.net/shijuvarghese/archive/2010/03/06/persisting-model-state-in-asp-net-mvc-using-html-serialize.aspx

Resources