Implementing custom session state provider in ASP.NET MVC - asp.net-mvc

I'm working on implementing a custom session state provider for my ASP.NET MVC application. My requirement is I've to store the session data as xml in a custom table in Sql server.
Can I use the existing sql session state provider (overriding some methods) or I've to create from scratch by implementing the abstract class SessionStateStoreProviderBase?

yes you can customize your class provider Session even with sql server or oracle. Just inherit from a class in your model inheriting from SessionStateStoreProviderBase and implementing the required methods that he sends, check the list of required methods here.
If you want to use an example, see here.
This example using odbc but simply replace for access class as OdbcConnection to SqlConnection and vice versa.
Good luck.

Why aren't you just using SQL server as your state provider? You can set it in the config and this happens automatically, then SQL server will store the data as serialized binary data and efficiently retrieve it?
The short answer is yes, you can, but it's re-inventing the wheel. Do you need to use the data for anything else or edit it yourself out of process? I'd be inclined to use a seperate process for this. You're going to create a bit of work for yourself doing this and you would be better to just save the xml property somwhere when you set it in sessiopn if you need to look at it later.
Make your xml document a session object
Session["MyCustomXml"] = mydoc;
var mydoc = Session["MyCustomXml"] as XmlDocument;
then use the following config so it's stored in sql server.
<sessionState
mode="SQLServer"
sqlConnectionString="data source=127.0.0.1;user id=<username>;password=<strongpassword>"
cookieless="false"
timeout="20"
/>
If you need to look at later, just save it to disk somwhere safely with the SessionId as the filename to keep it unique.

Related

keep variable throughout the life of the application in mvc

I need to keep variable throughout the life of the application. It shouldn't be disposed NEVER.
I was thinking of two methods:
Keep it the file
Store in database in separate table
But in the second case, create a separate table for one row isn't very clever.
So how to achieve that?
Depending on where the property is initialised:
It could be stored within the Application Scope -
There are different scopes with ASP.NET and other scopes are Session and Request
ASP.NET Application State Overview
ASP.NET Session State Overview
Alternatively set as a static property within the Global.asax
Set as a app setting in Web.Config if its immutable
<appSettings>
<add name="fixedProperty" value="fixedValue" />
</appSettings>
and reference anywhere within the application using
ConfigurationManager.AppSettings["fixedProperty"]
(although this call to configuration to should moved to a single static Settings file to make call to property reusable with one accessor to the web.config - type can also be converted from string to whatever you may require too)
As you already mentioned, persist to file or database - there is nothing wrong with persisting the single record to a database. That's what the data store is for.
You can make that variable as a static variable in a class like StaticData.java and use it with the class name. If you want to access the variable only at client side you can use localstorage.set().

Using Breeze for arbitrary server response

Have all a structure for creating complex queries and obtaining data on the client side using Breeze and webapi IQueryable<T>.
I would use this structure on the client side to call another webapi controller, intercept the result of the query, and use this to make an Excel file returned by HttpResponseMessage.
See: Returning binary file from controller in ASP.NET Web API
How can I use the executeQuery without getting return data in standard Breeze JSON and without interfering with the data on the client side cache to have the 'octet-stream'.
The goal is to create an 'Export to Excel' without existing frontend paging for a large volume of data.
If you don't want to track changes, call EntityQuery.noTracking() before calling executeQuery(). This will return raw javascript objects without breeze tracking capabilities.
You can't make executeQuery() return binary 'octet-stream' data. But you can use breeze ajax implementation:
var ajaxImpl = breeze.config.getAdapterInstance("ajax");
ajaxImpl.ajax() // by default it is a wrapper to jQuery.ajax
Look http://www.breezejs.com/documentation/customizing-ajax
Create a custom "data service adapter" and specify it when you create an EntityManager for this special purpose. It can be quite simple because you disable the most difficult parts to implement, the metadata and saveChanges methods.
You don't want to cache the results. Therefore, you make sure the manager's metadata store is empty and you should add the " no caching" QueryOption. [exact names escape me as I write this on my phone].
Make sure these steps are really adding tangible value
Specialized server operations often can be performed more simply with native AJAX components.
p.s. I just saw #didar 's answer which is consistent with mine. Blend these thoughts into your solution.

Is it possible to change object A on the client, but modify object B on the server? [Default Breeze WebApi]

I'm trying to implement something like commands in my breeze app, but I miss "a bit of indirection", between the model on the client and my database/EF db context.
So here is the question:
How can I modify (create/update or delete) entity on the server, which is not one of the entities modified (created/updated/deleted) on the client?
For example:
To allow user password change create a new CmdNewPassword entity (with OldPassword and NewPassword fields) on the client, but on the server check that old password is correct and update User.PasswordHash and User.PasswordSalt.
or
If new Invoice entity was created on the client, create new LogEntry entity on the server to keep a log of user actions.
Save interception (http://www.breezejs.com/documentation/custom-efcontextprovider#SaveInterception) says that entities may be added or removed from the map returned by BeforeSaveEntities, but I don't think it is possible to add anything to this map, because EntityInfo's properties have internal setters.
Edit: May 8, 2013 - As of v 1.3.3, available on the Breeze website, there is a now a new public ContextProvider.CreateEntityInfo method that you should be able to call from within your BeforeSaveEntities method.
You are right, and you are on the right path with the idea of modifying the saveMap passed into the BeforeSaveEntities method. Currently, you can remove and modify entities from the map but you have no good way to add one. I will try to get this fixed in the next release.

Understanding VS's ability to create database on first run

I'm working with a (.net4 / mvc3 ) solution file downloaded (from a reputable source) where a connection string exists in web.config but I don't see explicit instructions to create the database and there's no included '.mdf'. The first time I build I got a runtime error regarding lack of permissions to CREATE database. So I created a blank db and made sure the string referenced a SQL user that had .dbo/owner rights to the db just created.
But subsequent builds don't seem to execute that same initialize db script - where ever that's stored.
Where is this 'first use' convention for creating databases documented?
thx
That is a feature of Entity Framework Code First. I am not sure what you are looking for exactly, but searching for "EF Code First Initialization Strategy" might help.
For instance read this article: EF Code First DB Initialization Using Web.Config
I assume you are talking about Entity Framework, which allows you to create the database from an instance of an ObjectContext object, which is used in any of the three approaches in EF (database-, model- and code-first).
Look for a line that actually calls ObjectContext.CreateDatabase(). If one of the supported ADO.NET provides is used (SQL Server or SQL Server CE 4.0) this will generate the required SQL Statements. Assuming the classic Northwind example, you might find something like that:
NorthwindContext context = new NorthwindContext();
if (!context.DatabaseExists())
{
context.CreateDatabase();
}
If this is in fact a code-first application, "lalibi" is right about the initialization strategy which by default doesn't require you to explicitly create the database. (But my guess is, that it actually uses a statement internally very similar to mine).

ASP.NET MVC -> WCF -> NHibernate, how to efficiently update entity with data from viewmodel?

A week back, I had an ASP.NET MVC application that called on a logical POCO service layer to perform business logic against entities. One approach I commonly used was to use AutoMapper to map a populated viewmodel to an entity and call update on the entity (pseudo code below).
MyEntity myEntity = myService.GetEntity(param);
Mapper.CreateMap<MyEntityVM, MyEntity>();
Mapper.Map(myEntityVM, myEntity);
this.myService.UpdateEntity(myEntity);
The update call would take an instance of the entity and, through a repository, call NHibernate's Update method on the entity.
Well, I recently changed my logical service layer into WCF Web Services. I've noticed that the link NHibernate makes with an entity is now lost when the entity is sent from the service layer to my application. When I try to operate against the entity in the update method, things are in NHibernate's session that shouldn't be and vice-versa - it fails complaining about nulls on child identifiers and such.
So my question...
What can I do to efficiently take input from my populated viewmodel and ultimately end up modifying the object through NHibernate?
Is there a quick fix that I can apply with NHibernate?
Should I take a different approach in conveying the changes from the application to the service layer?
EDIT:
The best approach I can think of right now, is to create a new entity and map from the view model to the new entity (including the identifier). I would pass that to the service layer where it would retrieve the entity using the repository, map the changes using AutoMapper, and call the repository's update method. I will be mapping twice, but it might work (although I'll have to exclude a bunch of properties/children in the second mapping).
No quick fix. You've run into the change tracking over the wire issue. AFAIK NHibernate has no native way to handle this.
These may help:
https://forum.hibernate.org/viewtopic.php?f=25&t=989106
http://lunaverse.wordpress.com/2007/05/09/remoting-using-wcf-and-nhibernate/
In a nutshell your two options are to adjust your service to send state change information over the Nhibernate can read or load the objects, apply the changes and then save in your service layer.
Don't be afraid of doing a select before an update inside your service. This is good practice anyway to prevent concurrency issues.
I don't know if this is the best approach, but I wanted to pass along information on a quick fix with NHibernate.
From NHibernate.xml...
<member name="M:NHibernate.ISession.SaveOrUpdateCopy(System.Object)">
<summary>
Copy the state of the given object onto the persistent object with the same
identifier. If there is no persistent instance currently associated with
the session, it will be loaded. Return the persistent instance. If the
given instance is unsaved or does not exist in the database, save it and
return it as a newly persistent instance. Otherwise, the given instance
does not become associated with the session.
</summary>
<param name="obj">a transient instance with state to be copied</param>
<returns>an updated persistent instance</returns>
</member>
It's working although I haven't had time to examine the database calls to see if it's doing exactly what I expect it to do.

Resources