ASP .Net MVC + IIS 7.5 + Static field - c#

I have ASP .Net MVC project with additional MFC Service running in it (.svc file included in project, not separate project). I name it Concentrator. It have static field bookDays that is being set from DB in static constructor. It's being used in GetSlots method of Concentrator. Here is code (I have removed everything unrelated)
class Concentrator : IConcentrator
{
private static int bookDays = 0;
public static int BookDays {
get { return bookDays; }
set { bookDays = value; }
}
static RegConcentratorGeneral()
{
var settings = //DB query was here
if (settings != null)
BookDays = settings.BookDays;
}
public getSlotsResponse getSlots(getSlotsRequest request)
{
DateTime dateStart = DateTime.Now.AddDays(BookDays);
}
}
I have also settings-saving Controller:
public ActionResult Save(ConcentratorSettings ConcentratorParams)
{
//Saving settings in DB removed
RegConcentrator.BookDays = ConcentratorParams.BookDays;
}
That was working on my PC, on test IIS server, but fails on production. getSlots simply uses old value of BookDays that being set in constructor. Seems like it doesn't change when I setting it using controller. There is no exception, Save() method ever saves settings in DB, but getSlots produces results based on prevevious value anyway. When I have replaced using BookDays by DB query in getSlots(), problem have disappeared. What could be the reason of that? Production server isn't cluster.

Related

Independent sessions for each tabs C# WebApi / Angular2+

We are building aWeb app that allows users to open different projects they created using this app. The front-end is an Angular 4 app with a REST Architecture and the backend a C# Asp.net Web Api.
Our problem is that we store all our backend datas in a Session (because it's a huge object with mathematical datas and formulas in it), and when we open multiple projects in different tabs, the session become in common between each tabs so it causes interferences.
We are trying to find a way to attach each instance of the app (each project) with an unique session in the server. We look for using GUID stored in window.name for each tab, then sent to the server which has HttpContext.Current.Session["GUIDSessionID"]; that stores our object but we did not find the way to make it work, as we are beginners in c# development.
Here are the links we look for to find a solution (without success) :
http://blog.gauffin.org/2012/02/get-a-unique-session-in-each-browser-tab/
https://www.codeproject.com/Questions/364203/Stop-Sharing-Session-State-between-Multiple-Tabs-o
Thanks in advance.
Nikolas
Generate a unique session id a hash or something.
In Angular to store it can put locale localStorage.setItem('GUIDSessionID', 'YourSessionID');.
If you want to get it even after a refresh localStorage.getItem('GUIDSessionID');
If you login with a new generate new SessionID remove old localStorage.removeItem('GUIDSessionID') and set new.
The easiest way to achieve this is by -
reading the project ID from URL/querystring and put that in some hidden field on the page.
Create all the session variables with key starting that project ID.
For example, if your project ID is '654654481CEG', your session assignment will be something like this:
Session[string.Format("{0}-projectName", "654654481CEG")] = "WhateverYourValueIs";
While reading the value back from session, you will do the same -
string strprojectName = Session[string.Format("{0}-projectName", "654654481CEG")].ToString();
I had the same problem with a coworker and we used sort of sub-sessions:
//We changed this
HttpContext.Current.Session["x"] = x;
HttpContext.Current.Session["y"] = y;
//To this
HttpContext.Current.Session["guid"] = new SessionContent{x = x, y = y };
and we did as follow :
BackEnd
public static class SessionUtils
{
public class SessionContent
{
public XClass xProperty{ get; set; }
public YClass yProperty{ get; set; }
}
public static string GetSessionGUID(IHttpRouteData route)
{
return route.Values["guid"].ToString();
}
public static XClass GetSessionXProperty(HttpContextBase httpContextBase, IHttpRouteData route)
{
return ((SessionUtils.SessionContent)httpContextBase.Session[GetSessionGUID(route)]).xProperty;
}
public static void SetSessionXProperty(HttpContextBase httpContextBase, IHttpRouteData route, XClass xProperty)
{
((SessionUtils.SessionContent)httpContextBase.Session[GetSessionGUID(route)]).xProperty= xProperty;
}
public static YClass GetSessionYProperty(HttpContextBase httpContextBase, IHttpRouteData route)
{
return ((SessionUtils.SessionContent)httpContextBase.Session[GetSessionGUID(route)]).yProperty;
}
public static void SetSessionYProperty(HttpContextBase httpContextBase, IHttpRouteData route, YClass yProperty)
{
((SessionUtils.SessionContent)httpContextBase.Session[GetSessionGUID(route)]).yProperty= yProperty;
}
}
Here is an controller for example:
public class TestController : ApiController
{
private HttpContextBase _httpContext;
public TestController ()
{
_httpContext = new HttpContextWrapper(HttpContext.Current);
}
public AuditTrailController(HttpContextBase context)
{
_httpContext = context;
}
[HttpGet]
[Route("Send}")]
public HttpResponseMessage Send()
{
XClass x = SessionUtils.GetSessionXProperty(_httpContext, Request.GetRouteData());
HttpResponseMessage response = new HttpResponseMessage();
response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(JsonConvert.SerializeObject(x), System.Text.Encoding.UTF8, "application/json");
return response;
}
}
And in Angular front we just generate a GUID, send it to the back end while initiating the project and add it to each request we make.
window.name = UUID.UUID();
Then in services :
return this.http.get(environment.baseUrl + '/' + window.name + '/myController/')
.map(res => res.json());

ASP.NET is it possible to use Session & HttpContext.Application in a library

I have the following code in a HttpGet method in a Controller
Session["var1"] = "someval1";
HttpContext.Application["var2"] = "someval2";
I wish to put away this code in a library [dll] so that in the library I have
// Inside DLL Library
// namespace MyNS, class MyCl
public void InitVars()
{
Session["var1"] = "someval1";
HttpContext.Application["var2"] = "someval2";
}
And the call this from my controller Get method
// In controller class HttpGet
InitVars();
How do I access the Session & the Application objects in the Library
I get the errors
The name Session does not exist in the current context
The name HttpContext does not exist in the current context
How can this be done?
You just need to open up the code library .csproj in Visual Studio and set a reference to System.Web.dll and the same code will work in the DLL.
You can get a reference to the current HttpContext using the following code:
var context = System.Web.HttpContext.Current;
after which you can simply call
context.Session["var1"] = "someval1";
context.Application["var2"] = "someval2";
This works
void InitLogin(System.Web.HttpSessionStateBase Session,
System.Web.HttpApplicationStateBase Application)
{
Session["var1"] = "someval1";
Application["var2"] = "someval2";
}
and call it as
InitVars(Session, Application);
How do I access the Session & the Application objects in the Library
Don't do it directly, you'll couple your code. I recommend using the Adapter Pattern. Something like this (untested):
Class Library:
public interface IStorage
{
T GetSession<T>(string key);
void SetSession<T>(string key, T value);
T GetGlobal<T>(string key);
void SetGlobal<T>(string key, T value);
}
public void InitVars(IStorage storage)
{
storage.SetSession("var1", "someval1");
storage.SetGlobal("var2", "somval2");
}
Web App:
public class WebStorage : IStorage
{
public T GetSession<T>(string key)
{
var result = Session[key] as T;
return result;
}
public void SetSession<T>(string key, T value)
{
Session[key] = value;
}
// etc with Global
}
InitVars(new WebStorage);
Now you have no dependencies on any web classes. If down the road you decide to use asp.net core (which has no HttpContext.Current etc etc) you can easily modify your WebStorage class without having to change your class library.

How can I use EF6 and a SQL Server CE database when I have no access to App.config?

I am having an issue with code-based configuration of Entity Framework 6 and SQL Server CE 4.0. My project is a COM component class library that must work with multiple applications and I cannot know ahead of time which applications will consume the component, so I can't use app.config as a configuration mechanism.
I am attempting to use code-based configuration, as follows. First, my context class:
[DbConfigurationType(typeof(DataConfiguration))]
internal class SlewTargetsDbContext : DbContext
{
public SlewTargetsDbContext(string connectionString):base(connectionString){ }
public DbSet<SlewTarget> Targets { get; set; }
#region Overrides of DbContext
/// <summary>
/// Degenerate override prevents any changes from being saved.
/// </summary>
public override int SaveChanges() { return 0; }
#endregion
}
Here is the configuration class:
public class DataConfiguration : DbConfiguration
{
public DataConfiguration()
{
SetExecutionStrategy("System.Data.SqlServerCe.4.0", () => new DefaultExecutionStrategy());
SetProviderFactory("System.Data.SqlServerCe.4.0", new SqlCeProviderFactory());
SetProviderServices("System.Data.SqlServerCe.4.0", SqlCeProviderServices.Instance);
}
}
I have a static method that creates instances of the data contexts, as follows:
public static SlewTargetsDbContext GetTargetDatabase()
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyFileName = assembly.Location;
var path = Path.GetDirectoryName(assemblyFileName);
var dbFile = Path.Combine(path, "SlewTargets.sdf");
var builder = new SqlCeConnectionStringBuilder();
builder.DataSource = dbFile;
builder.FileMode = "Read Only";
builder.TempFilePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var connectionString = builder.ToString();
var context = new SlewTargetsDbContext(connectionString);
return context;
}
And finally, I use the data context like this:
Maybe<SlewTarget> LookupTargetFromCoordinates(RightAscension ra, Declination dec)
{
const double WithinOneMinute = 1.0 / 60.0; // 1 minute of arc
var db = CompositionRoot.GetTargetDatabase();
var targets = from item in db.Targets
where item.RightAscension.IsCloseTo(ra.Value, WithinOneMinute)
&& item.Declination.IsCloseTo(dec.Value, WithinOneMinute)
select item;
var found = targets.ToList();
return found.Any() ? new Maybe<SlewTarget>(targets.First()) : Maybe<SlewTarget>.Empty;
}
When I run this code, I get an exception at the point where I create an instance of the data context:
Unable to determine the DbProviderFactory type for connection of type 'System.Data.SqlServerCe.SqlCeConnection'. Make sure that the ADO.NET provider is installed or registered in the application config.
My configuration class explicitly sets the provide factory, however, if I set a breakpoint on that code, it is never hit. So it seems like EF6 is ignoring my configuration. I'm reliant on the attribute on my data context class because I can't use app.config, but that doesn't seem to be working.
I've probably missed something simple but I can't see it. Any ideas?
[Update 2016-02-16 10:30] Removing the [DbConfigurationType] attribute from my data context has helped and now the configuration code is executing. However, now I'm getting this error:
The underlying provider failed on Open.
The InnerException is:
Internal error: Cannot open the shared memory region.
That's a System.Data.SqlServerCe.SqlCeException.
Does that ring any bells?

ASP.NET manage site settings globally using database

I am working on a project where I need to store settings for various areas in the application. These settings aren't stored in the app.config because there is an admin page where the admin can change the settings (client does not want these settings in the app.config)
I tried to implement a static class to access the settings globally but my concern is using the dbcontext in a static class as I don't think it's the best choice as well i'd like the settings to be strongly-typed and right now everything is a string.
I am not sure how else I can access my appsettings table in the database and still make it easy to call throughout the application, like ConfigurationManager.AppSetting["settingName"];
public static class AppManager
{
private static readonly IUnitOfWork UnitOfWork = new UnitOfWork(new DatabaseContext());
public static IEnumerable<AppSetting> GetAll()
{
return UnitOfWork.AppSettings.GetAll();
}
public static AppSetting Get(Guid id)
{
return UnitOfWork.AppSettings.Get(id);
}
public static string GetValue(string name)
{
return UnitOfWork.AppSettings.GetValue(name);
}
public static void Update(string name, string value)
{
var setting = UnitOfWork.AppSettings.Get(name);
if(setting == null) return;
setting.Value = value;
UnitOfWork.Complete();
}
}

Asp.net MVC 5 session and storage singleton class don't work on iis production

I have problem with ASP.NET MVC5. It works well on Visual Studio 2013 update 2 but on production or test server 2008 or 2012 it is not.
I have simple thing to do. Deliver bunch of variables form one view to other. Naturally I use:
HttpContext.Session["Mailpack_ID"] = id;
Doesn't work on Windows Server (both iis 7.5&8 ). I use this solution:
ASP.NET MVC - Session is null
Solution 1 - Don't work, so I write my own class witch can storage variables (avoid using session):
public class StorageSingleton
{
private static StorageSingleton instance;
private StorageSingleton() { }
public static StorageSingleton Instance
{
get
{
if (instance == null)
{
instance = new StorageSingleton();
}
return instance;
}
}
public string Mailpack_ID { get; set; }
}
Use in code:
var storage = StorageSingleton.Instance;
storage.Mailpack_ID = id.ToString();
It was surprise for me - but nothing. I think when I use class all information are in code, but I get the same error. I have any idea. Any help?

Categories

Resources