I cannot figure out how to fix this loop issue when i call a function like
new Common.Utility.Parameter().Get(Common.Constants.Parameter.SomeParameter);
Probably the error is caused by isHttpsCookie that recall the Parameter.Get()
Utility.cs
public static class Utility
{
public class Parameter
{
public string Get(string key)
{
string cookie = new Cookie().Read(key);
if (cookie == null)
{
var parameter = new Models.Parameter();
using (var db = new MyEntities())
parameter = db.Parameters.Where(w => w.Key == key).FirstOrDefault<Models.Parameter>();
if (parameter != null)
{
new Cookie().Write(key, parameter.Value);
return parameter.Value;
}
else
return string.Empty;
}
else
return cookie;
}
}
}
Cookie.cs
public class Cookie
{
private bool isHttpsCookie = Convert.ToBoolean(new Utility.Parameter().Get(Constants.Parameter.IsHttps)); // Loop here?
public string Read(string cookieName)
{
HttpCookie httpCookie = HttpContext.Current.Request.Cookies[HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name + "_" + cookieName];
return httpCookie != null ? HttpContext.Current.Server.HtmlEncode(httpCookie.Value).Trim() : string.Empty;
}
public void Write(string cookieName, string cookieValue, bool isHttpCookie = true)
{
if (isHttpsCookie)
isHttpCookie = false;
var aCookie = new HttpCookie(HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name + "_" + cookieName)
{Value = cookieValue, Expires = Common.Constants.Cookie.DefaultExpires, HttpOnly = isHttpCookie};
HttpContext.Current.Response.Cookies.Add(aCookie);
}
}
Apparently, your code is falling into a sort of recursion where you suspect it is. What I'm having trouble with is why are you creating new objects just to call a single method. Looks like you could have them as static methods in your classes, so no object creation would be needed, thus no 'looping'.
Have a closer look at your Cookie.Write() and Parameter.Get() method, they are calling each other. When you declare isHttpsCookie, you call Parameter.Get(). In the Parameter.Get(), if the condition is valid, it will call to Cookie.Write(). In its turn, when you call new Cookie(), the isHttpsCookie is called again and it's continuing forever.
Another point at this code:
if (isHttpsCookie)
isHttpCookie = false;
do you try to say that isHttpsCookie should be false at all time? so why do you need to declare this?
Solution: Do like #Takeshi said: those methods can be declared as static so no class declaration is required to called them.
You are correct in what you suspect. the isHttpsCookie declaration is causing you grief.
When the Cookie object is created it goes away and executes the method get from your utility class which creates an instance of cookie. Therefor you have your recursion.
You will need to change the way you initialise isHttpsCookie. Maybe only initialise / check if you are doing a write. After all you are most likely going to read more often than write.
Hope that helps.
Related
So what I really want is somewhat usable tab completion in a PS module.
ValidateSet seems to be the way to go here.
Unfortunately my data is dynamic, so I cannot annotate the parameter with all valid values upfront.
DynamicParameters/IDynamicParameters seems to be the solution for that problem.
Putting these things together (and reducing my failure to a simple test case) we end up with:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading.Tasks;
namespace PSDummy
{
[Cmdlet(VerbsCommon.Get, "BookDetails")]
public class GetBookDetails : Cmdlet, IDynamicParameters
{
IDictionary<string, string[]> m_dummyData = new Dictionary<string, string[]> {
{"Terry Pratchett", new [] {"Small Gods", "Mort", "Eric"}},
{"Douglas Adams", new [] {"Hitchhiker's Guide", "The Meaning of Liff"}}
};
private RuntimeDefinedParameter m_authorParameter;
private RuntimeDefinedParameter m_bookParameter;
protected override void ProcessRecord()
{
// Do stuff here..
}
public object GetDynamicParameters()
{
var parameters = new RuntimeDefinedParameterDictionary();
m_authorParameter = CreateAuthorParameter();
m_bookParameter = CreateBookParameter();
parameters.Add(m_authorParameter.Name, m_authorParameter);
parameters.Add(m_bookParameter.Name, m_bookParameter);
return parameters;
}
private RuntimeDefinedParameter CreateAuthorParameter()
{
var p = new RuntimeDefinedParameter(
"Author",
typeof(string),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 0,
Mandatory = true
},
new ValidateSetAttribute(m_dummyData.Keys.ToArray()),
new ValidateNotNullOrEmptyAttribute()
});
// Actually this is always mandatory, but sometimes I can fall back to a default
// value. How? p.Value = mydefault?
return p;
}
private RuntimeDefinedParameter CreateBookParameter()
{
// How to define a ValidateSet based on the parameter value for
// author?
var p = new RuntimeDefinedParameter(
"Book",
typeof(string),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 1,
Mandatory = true
},
new ValidateSetAttribute(new string[1] { string.Empty }/* cannot fill this, because I cannot access the author */),
new ValidateNotNullOrEmptyAttribute()
});
return p;
}
}
}
Unfortunately this tiny snippet causes a lot of issues already. Ordered descending:
I fail to see how I can create a connection between the parameters. If you pick an author, you should only be able to pick a book that matches the author. So far GetDynamicParameters() always seems stateless though: I see no way to access the value of a different/earlier dynamic parameter. Tried keeping it in a field, tried searching MyInvocation - no luck. Is that even possible?
How do you define a default value for mandatory parameter? Doesn't fit the silly example, but let's say you can store your favorite author. From now on I want to default to that author, but having a pointer to an author is still mandatory. Either you gave me a default (and can still specify something else) or you need to be explicit.
Tab completion for strings with spaces seems weird/broken/limited - because it doesn't enclose the value with quotes (like cmd.exe would do, for example, if you type dir C:\Program <tab>). So tab completion actually breaks the invocation (if the issues above would be resolved, Get-BookDetails Ter<tab> would/will expand to Get-BookDetails Terry Pratchett which puts the last name in parameter position 1 aka 'book'.
Shouldn't be so hard, surely someone did something similar already?
Update: After another good day of tinkering and fooling around I don't see a way to make this work. The commandlet is stateless and will be instantiated over and over again. At the point in time when I can define dynamic parameters (GetDynamicParameters) I cannot access their (current) values/see what they'd be bound to - e.g. MyInvocation.BoundParameters is zero. I'll leave the question open, but it seems as if this just isn't supported. All the examples I see add a dynamic parameter based on the value of a static one - and that's not relevant here. Bugger.
I think this works. Unfortunately, it uses reflection to get at some of the cmdlet's private members for your first bullet. I got the idea from Garrett Serack. I'm not sure if I completely understood how to do the default author, so I made it so that the last valid author is stored in a static field so you don't need -Author the next time.
Here's the code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading.Tasks;
namespace PSDummy
{
internal class DynParamQuotedString {
/*
This works around the PowerShell bug where ValidateSet values aren't quoted when necessary, and
adding the quotes breaks it. Example:
ValidateSet valid values = 'Test string' (The quotes are part of the string)
PowerShell parameter binding would interperet that as [Test string] (no single quotes), which wouldn't match
the valid value (which has the quotes). If you make the parameter a DynParamQuotedString, though,
the parameter binder will coerce [Test string] into an instance of DynParamQuotedString, and the binder will
call ToString() on the object, which will add the quotes back in.
*/
internal static string DefaultQuoteCharacter = "'";
public DynParamQuotedString(string quotedString) : this(quotedString, DefaultQuoteCharacter) {}
public DynParamQuotedString(string quotedString, string quoteCharacter) {
OriginalString = quotedString;
_quoteCharacter = quoteCharacter;
}
public string OriginalString { get; set; }
string _quoteCharacter;
public override string ToString() {
// I'm sure this is missing some other characters that need to be escaped. Feel free to add more:
if (System.Text.RegularExpressions.Regex.IsMatch(OriginalString, #"\s|\(|\)|""|'")) {
return string.Format("{1}{0}{1}", OriginalString.Replace(_quoteCharacter, string.Format("{0}{0}", _quoteCharacter)), _quoteCharacter);
}
else {
return OriginalString;
}
}
public static string[] GetQuotedStrings(IEnumerable<string> values) {
var returnList = new List<string>();
foreach (string currentValue in values) {
returnList.Add((new DynParamQuotedString(currentValue)).ToString());
}
return returnList.ToArray();
}
}
[Cmdlet(VerbsCommon.Get, "BookDetails")]
public class GetBookDetails : PSCmdlet, IDynamicParameters
{
IDictionary<string, string[]> m_dummyData = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase) {
{"Terry Pratchett", new [] {"Small Gods", "Mort", "Eric"}},
{"Douglas Adams", new [] {"Hitchhiker's Guide", "The Meaning of Liff"}},
{"An 'Author' (notice the ')", new [] {"A \"book\"", "Another 'book'","NoSpace(ButCharacterThatShouldBeEscaped)", "NoSpace'Quoted'", "NoSpace\"Quoted\""}} // Test value I added
};
protected override void ProcessRecord()
{
WriteObject(string.Format("Author = {0}", _author));
WriteObject(string.Format("Book = {0}", ((DynParamQuotedString) MyInvocation.BoundParameters["Book"]).OriginalString));
}
// Making this static means it should keep track of the last author used
static string _author;
public object GetDynamicParameters()
{
// Get 'Author' if found, otherwise get first unnamed value
string author = GetUnboundValue("Author", 0) as string;
if (!string.IsNullOrEmpty(author)) {
_author = author.Trim('\'').Replace(
string.Format("{0}{0}", DynParamQuotedString.DefaultQuoteCharacter),
DynParamQuotedString.DefaultQuoteCharacter
);
}
var parameters = new RuntimeDefinedParameterDictionary();
bool isAuthorParamMandatory = true;
if (!string.IsNullOrEmpty(_author) && m_dummyData.ContainsKey(_author)) {
isAuthorParamMandatory = false;
var m_bookParameter = new RuntimeDefinedParameter(
"Book",
typeof(DynParamQuotedString),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 1,
Mandatory = true
},
new ValidateSetAttribute(DynParamQuotedString.GetQuotedStrings(m_dummyData[_author])),
new ValidateNotNullOrEmptyAttribute()
}
);
parameters.Add(m_bookParameter.Name, m_bookParameter);
}
// Create author parameter. Parameter isn't mandatory if _author
// has a valid author in it
var m_authorParameter = new RuntimeDefinedParameter(
"Author",
typeof(DynParamQuotedString),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 0,
Mandatory = isAuthorParamMandatory
},
new ValidateSetAttribute(DynParamQuotedString.GetQuotedStrings(m_dummyData.Keys.ToArray())),
new ValidateNotNullOrEmptyAttribute()
}
);
parameters.Add(m_authorParameter.Name, m_authorParameter);
return parameters;
}
/*
TryGetProperty() and GetUnboundValue() are from here: https://gist.github.com/fearthecowboy/1936f841d3a81710ae87
Source created a dictionary for all unbound values; I had issues getting ValidateSet on Author parameter to work
if I used that directly for some reason, but changing it into a function to get a specific parameter seems to work
*/
object TryGetProperty(object instance, string fieldName) {
var bindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
// any access of a null object returns null.
if (instance == null || string.IsNullOrEmpty(fieldName)) {
return null;
}
var propertyInfo = instance.GetType().GetProperty(fieldName, bindingFlags);
if (propertyInfo != null) {
try {
return propertyInfo.GetValue(instance, null);
}
catch {
}
}
// maybe it's a field
var fieldInfo = instance.GetType().GetField(fieldName, bindingFlags);
if (fieldInfo!= null) {
try {
return fieldInfo.GetValue(instance);
}
catch {
}
}
// no match, return null.
return null;
}
object GetUnboundValue(string paramName) {
return GetUnboundValue(paramName, -1);
}
object GetUnboundValue(string paramName, int unnamedPosition) {
// If paramName isn't found, value at unnamedPosition will be returned instead
var context = TryGetProperty(this, "Context");
var processor = TryGetProperty(context, "CurrentCommandProcessor");
var parameterBinder = TryGetProperty(processor, "CmdletParameterBinderController");
var args = TryGetProperty(parameterBinder, "UnboundArguments") as System.Collections.IEnumerable;
if (args != null) {
var currentParameterName = string.Empty;
object unnamedValue = null;
int i = 0;
foreach (var arg in args) {
var isParameterName = TryGetProperty(arg, "ParameterNameSpecified");
if (isParameterName != null && true.Equals(isParameterName)) {
string parameterName = TryGetProperty(arg, "ParameterName") as string;
currentParameterName = parameterName;
continue;
}
// Treat as a value:
var parameterValue = TryGetProperty(arg, "ArgumentValue");
if (currentParameterName != string.Empty) {
// Found currentParameterName's value. If it matches paramName, return
// it
if (currentParameterName.Equals(paramName, StringComparison.OrdinalIgnoreCase)) {
return parameterValue;
}
}
else if (i++ == unnamedPosition) {
unnamedValue = parameterValue; // Save this for later in case paramName isn't found
}
// Found a value, so currentParameterName needs to be cleared
currentParameterName = string.Empty;
}
if (unnamedValue != null) {
return unnamedValue;
}
}
return null;
}
}
}
I have a Non Static class which contains a number of properties
private static List<FileClass> FileClassList = new List<FileClass>();
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
{
this.FileID = FileIDCounter;
this.Name = finfo.Name;
this.FullName = finfo.FullName;
this.Attributes = GetFileAttributes(finfo);
this.CreationTime = finfo.CreationTime;
this.Extension = finfo.Extension;
this.isReadOnly = finfo.IsReadOnly;
this.LastAccessTime = finfo.LastAccessTime;
this.LastWriteTime = finfo.LastWriteTime;
this.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(this);
if (FileClassFileAdded != null) FileClassFileAdded(this);
}
Although the Class is added FileClassList.Add(this); the final result is a FileClassList filled with whatever the last instance of the class contained and not the this.Properties values.
So, how do I add the current instance of the FileClass to the FileClassList so that the contents of the FileClassList contains the different instances of the FileClass.
Here is what your issue most likely is...
Having this:
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
Somewhere you probably do:
MyClassWhichAddsAFile cls = new MyClassWhichAddsAFile();
cls.AddFile(fileInfo1);
cls.AddFile(fileInfo2);
cls.AddFile(fileInfo3);
While you need to do (under this design):
MyClassWhichAddsAFile cls1 = new MyClassWhichAddsAFile();
cls1.AddFile(fileInfo1);
MyClassWhichAddsAFile cls2 = new MyClassWhichAddsAFile();
cls2.AddFile(fileInfo2);
........
Again, I am not discussing your design here or how to do it right. I am telling you that your problem is probably comes out from this situation
I think you have your design slightly askew. I don't think that AddFile should be part of FileClassList rather.
However in leiu of not having another place to hold it. I'd say do this:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
theClass.FileID = FileIDCounter;
theClass.Name = finfo.Name;
theClass.FullName = finfo.FullName;
theClass.Attributes = GetFileAttributes(finfo);
theClass.CreationTime = finfo.CreationTime;
theClass.Extension = finfo.Extension;
theClass.isReadOnly = finfo.IsReadOnly;
theClass.LastAccessTime = finfo.LastAccessTime;
theClass.LastWriteTime = finfo.LastWriteTime;
theClass.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
A better approach would be to create a contrstuctor on FileClass that takes a FileInfo and fills these properties in and call it like this:
var someFileClass = new FileClass(theFileInfo);
FileClass.AddFile(someClassFile);
and AddFile would be:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
even then I think the AddFile should be a method on the the caller not the callee!
I am using Chello (the c# wrapper for the Trello API). I need to pass the argument "createCard" as per the documentation here: https://trello.com/docs/api/card/index.html
And this is the function I am using from Chello:
public IEnumerable<CardUpdateAction> ForCard(string cardId, object args)
{
string queryString = BuildQueryString(args);
return GetRequest<List<CardUpdateAction>>("/cards/{0}/actions?{1}", cardId, queryString);
}
I have tried calling this in this way:
List<CardUpdateAction> cua = chello.CardUpdates.ForCard("5264d37736695b2821001d7a","createCard").ToList();
but I get the error: Parameter Count Mismatch
on this function:
protected static string BuildQueryString(object args)
{
string queryString = String.Empty;
if (args != null)
{
StringBuilder sb = new StringBuilder();
foreach (var prop in args.GetType().GetProperties())
{
sb.AppendFormat("{0}={1}&", prop.Name, prop.GetValue(args, null));
}
if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
queryString = sb.ToString();
}
return queryString;
}
The problem is the fact that your API you are using expects you to pass in a class that has public properties equal to the tags you want to use.
This is very easy to do using Anonymous Types (I am doing a slightly different example to help illustrate a point)
//This will cause BuildQueryString to return "actions=createCard&action_fields=data,type,date"
var options = new { actions = "createCard", action_fields = "data,type,date" };
List<CardUpdateAction> cua = chello.CardUpdates.ForCard("5264d37736695b2821001d7a",options).ToList();
string is an object. Every type in .NET platform inherits from Object. This is called Unified Type System.
On the other hand, we have the Liskov Substitution Principle, which put simply, says that if B is a subtype of A (B is A), then you should be able to use B, wherever A is used.
Based on these reasons, you can pass string to any method that accepts an object as an argument.
You can test it:
public void DoSomething(object args)
{
}
public void Main()
{
DoSomething("some string argument, instead of the object");
}
It works just fine. No error.
I need to check if cookie is present with value or not. But I wonder if there is some quick and good way of doing so since if I need to check 3 cookies it seems bad to check with if or try.
Why it does not assign empty string to my variable if cookie is not present? Instead it shows Object reference not set to an instance of an object.
My code (it works, but it seems too big for this task, I think there should be a better way of doing this)
// First I need to asign empty variables and I don't like this
string randomHash = string.Empty;
string browserHash = string.Empty;
int userID = 0;
// Second I need to add this huge block of try/catch just to get cookies
// It's fine since I need all three values in this example so if one fails all fails
try
{
randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
userID = Convert.ToInt32(Request.Cookies["userID"].Value);
}
catch
{
// And of course there is nothing to catch here
}
As you can see I have this huge block just to get cookies. What I would like is something like this:
// Gives value on success, null on cookie that is not found
string randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
string browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
int userID = Convert.ToInt32(Request.Cookies["userID"].Value);
Edit
Maybe I can somehow override the .Value method to my liking?
Just check if the cookie is null:
if(Request.Cookies["randomHash"] != null)
{
//do something
}
NOTE: The "Better" way of doing this is to write good code that is both readable and reliable. It doesn't assign empty string because this is not how C# works, you are trying to call the Value property on a null object (HttpCookie) - you cannot use null objects because there is nothing to use.
Converting to an int you still need to avoid parse errors, but you can use this built in method:
int.TryParse(cookieString, out userID);
which brings on another point? Why are you storing the userID in a cookie? this can be changed by the end user - I don't know how you plan on using this but would I be right to assume this is a big security hole?
or with a little helper function:
public string GetCookieValueOrDefault(string cookieName)
{
HttpCookie cookie = Request.Cookies[cookieName];
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = GetCookieValueOrDefault("randomHash");
Or with an Extension method:
public static string GetValueOrDefault(this HttpCookie cookie)
{
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = Request.Cookies["randomHash"].GetValueOrDefault();
I am busy converting a web application to MVC and have some information saved to Application variables used across multiple tenants/accounts to make things a bit more efficient.
I realise the point of MVC is to keep things as stateless as possible, Sesion State obviously makes sense to have and exists in MVC but we dont want to just convert Application to Session variables as we would rather have something more global and more secure. Do MVC applications have Application Variables? I have seen some examples where caching is used? Is this now standard and How robust/secure is this compared to Application/Session State?
Yes, you can access Application variables from .NET MVC. Here's how:
System.Web.HttpContext.Current.Application.Lock();
System.Web.HttpContext.Current.Application["Name"] = "Value";
System.Web.HttpContext.Current.Application.UnLock();
Session state or the Cache are better choices. They are mockable in MVC and are designed to store session and application-scoped data.
Static classes seems like a popular choice here. However static classes create dependencies between your types and make versioning/testing harder. Its also a bit of an odd pattern to use in a framework that is designed to break apart these kinds of dependencies. For instance, the standard ASP.NET framework is riddled with statics and sealed types. These are all replaced with mock-able instances.
"Secure" is a bit unclear in this context. Exactly what do you mean by "secure?"
I implemented something like below as an Extension for Global state variable. I put things like Site title,Service Endpoints, authorized roles
public static class ApplicationStateExtension
{
public static T GetSetApplicationState<T>(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
{
T retVal = default(T);
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
if (objectValue != null)
appState[objectName] = objectValue;
}
if (appState[objectName] != null)
retVal = (T)appState[objectName];
appState.UnLock();
return retVal;
}
public static object GetSetApplicationState(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
{
object retVal = null;
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
if (objectValue != null)
appState[objectName] = objectValue;
}
if (appState[objectName] != null)
retVal = appState[objectName];
appState.UnLock();
return retVal;
}
public static void SetApplicationState(this HttpApplicationState appState, string objectName, object objectValue, int syncCheckMinutes = 0)
{
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
appState[objectName] = objectValue;
}
appState.UnLock();
}
public static object GetApplicationState(this HttpApplicationState appState, string objectName)
{
object retVal = null;
appState.Lock();
if (appState[objectName] != null)
retVal = appState[objectName];
appState.UnLock();
return retVal;
}
public static T GetApplicationState<T>(this HttpApplicationState appState, string objectName)
{
T retVal = default(T);
appState.Lock();
if (appState[objectName] != null)
retVal = (T)appState[objectName];
appState.UnLock();
return retVal;
}
}
So I can set them from Global.asax.cs something like this
Application.SetApplicationState("UISiteTitle",paramHelper.GetUIConfigXML<XMLParams.UISiteOptions>("UISiteOptions")
.SiteOptionCollection.Where(v => v.name.Equals("title", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault().value););
or
var uiPermissions = Application.GetSetApplicationState<XMLParams.UIPermissions>("UIPermissions", paramHelper.GetUIConfigXML<XMLParams.UIPermissions>("UIPermissions"), 30);
You can declare Application variables in Application_Start like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
var e = "Hello";
Application["value"] = e;
}
To access this on controller write:
string appVar = HttpContext.Application["value"] as string;
Make a static class?
Do they have Application Variables? Yes, MVC is a framework that sits on top of the normal asp.net framework.
I would however create a static class that uses a cache store as it's backing.