I know this has been asked in several different ways, but I am not sure my specific problem has been asked. Due to Business rules, I can not use a db for temp storage of data between views. Static Variables are out (multi-user). I'm trying to avoid session and tempdata. I'll be storing about 9-12 models worth of data that will slow page load if I use Viewstate. I have multi-paged forms that will need to be refilled if the user returns to a form. I know this isn't the ideal way, but can anyone suggest a way to persist this data for multiple models other than session variables? Tempdata would need to be re-written per view I assume. I can't supply code and I know this is not a favorable design, but the rules are constricting.
Thank you.
I don't think there is anything wrong with using Session, even for MVC. It's a tool, use it when you need it. I find that most people tend to avoid Session because the code is usually pretty ugly. I like to use a Generic Wrapper around objects I need to store in session which provide a Strongly-Typed and Re-usable Class (example):
public abstract class SessionBase<T> where T : new()
{
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
// if you never want to return a null value
if (instance == null)
{
HttpContext.Current.Session[Key] = instance = new T();
}
return instance;
}
set
{
HttpContext.Current.Session[Key] = value;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
HttpContext.Current.Session[Key] = null;
}
}
}
Create your class that needs to be stored:
[Serializable] // The only requirement
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Create your Concrete type: (Really really easy?)
public class PersonSession : SessionBase<Person> { }
Use it whenever you want, with whatever you want (as long as it's serializable)
public ActionResult Test()
{
var Person = db.GetPerson();
PersonSession.Current = Person;
this.View();
}
[HttpPost]
public ActionResult Test(Person)
{
if (Person.FirstName != PersonSession.Current.FirstName)
{
// etc, etc
PersonSession.Clear();
}
}
Related
I am currently working on a game in XNA and I'm not sure on how I should go about doing the following...
I have a base class of buildings as such
public class BuildingsBase
{
private int _hp;
public int hp
{
get { return _hp; }
set { _hp= value; }
}
private int _woodRequired;
public int woodRequired
{
get { return _woodRequired; }
set { _woodRequired = value; }
}
}
I then have multiple subclasses for building types eg.
public class TownHall:BuildingsBase
{
public int foodHeld;
public TownHall()
{
foodHeld = 100;
woodRequired = 500;
}
}
My question is, what is the best way of setting the default values for building subclasses.
For example, the woodRequired for a townhall is set to 500 but at various places in code I need to access this value before I have an instance of townhall declared (When checking if there is enough wood to build).
I currently have a global array of default variables for each building type but im wondering if there is a better way of doing this.
if (Globals.buildingDefaults[BuildingType.Townhall].woodRequired < Globals.currentWood)
{
Townhall newTH = new Townhall();
}
Usually what happens is that they create a flyweight (see pattern). This object contains properties that are the same for every instance anyway. There's no need to change (or actually store) the required amount of wood for each instance separately.
In a very basic design it would look like:
class BuildingTemplate
{
public int WoodRequired { get; set; }
}
class Templates
{
public static BuildingTemplate TownHall { get; set; }
}
In the end you'd be calling a method like:
public bool CanBuildTownHall(Player player)
{
return player.HasEnoughResources(Templates.TownHall);
}
Of course, you can use a dictionary for template retrieval, and players shouldn't really know about building requirements. I'm just illustrating the pattern here.
If the player has enough resources, you can use the template to subtract the amount and create an actual instance of the TownHall. It's nice to have an reference to the actual template, because you'd probably be accessing other global properties that are valid for all TownHalls as well (such as audio/visuals/...).
class TownHall
{
public TownHall(BuildingTemplate template)
{
_template = template;
}
}
I'm basically trying to create a class that holds all the session information, then set and get it at will.
here is my call Session["SessionInformation"] = new SessionVar.UserSession();
and here is that class
public static class SessionVar
{
public class UserSession
{
public string FullName
{
get;
set;
}
public string HomeURL
{
get;
set;
}
public bool ValidUser
{
get;
set;
}
public int CountID
{
get;
set;
}
}
}
Lets say in this example I have a comboBox called CountID_ComboBox and on SelectedIndexChanged I want to set the users specific Session["SessionInformation"] CountID to the value of the combobox. How is that done?
protected void CountID_ComboBox_SelectedIndexChanged(object sender, Telerik.Web.UI.RadComboBoxSelectedIndexChangedEventArgs e)
{
//set the session variable here
}
Also, is there a way to foreach loop the strings in the class. Basically I want to see if any of those variables in that class is null.
So you've created this strongly typed UserSession class to handle your session variables. That's nice, specially if you have a big project, with lots of forms and (junior) developers.
You already know the most important part: for each new session, we'll have one, and only one UserSession object.
Now, let's move on to the part where you actually use it. You can retrieve the object's reference using ((SessionVar.UserSession)Session["SessionInformation"]). Let's dive into it:
Session["something"] returns an object
You want your UserSession object
We cast it using ((SessionVar.UserSession)Session["SessionInformation"]) and your done!
Now, let's say that, later on, you decide to move that object from the session to the viewstate (I'm not saying that this is a good idea, mind you). If you have that code scattered around your project, then it'll be a pain to manage that change.
So, the idea is to have a base page, from which all your pages will inherit. Something like:
public class BasePage : System.Web.UI.Page
{
...
}
And you place the code to retrieve your UserSession there, like:
public class BasePage : System.Web.UI.Page
{
public UserSession CurrentUserSession
{
get
{
UserSession userSession = null;
if (Session["UserSession"] == null)
{
userSession = new UserSession();
Session["UserSession"] = userSession;
}
else
userSession = (UserSession)Session["UserSession"];
return userSession;
}
private set { }
}
}
Bonus: note that, on the code above, I'm suggesting a way to ensure that you get one and only one object for the current user.
Finally, in order to get a list of the string properties that are empty, you can use the following method (place it inside UserSession):
public List<string> GetEmptyStringAttributes()
{
List<string> emptyStringAttributes = new List<string>();
Type type = this.GetType();
foreach (System.Reflection.PropertyInfo property in type.GetProperties())
{
if (property.PropertyType == typeof(String))
{
string value = property.GetValue(this) as string;
if (string.IsNullOrWhiteSpace(value))
emptyStringAttributes.Add(property.Name);
}
}
return emptyStringAttributes;
}
}
In case you can't find the combo box from your code behind, I'll use sender just to be sure we have the correct control.
var cBox = (RadComboBox)sender;
(SessionVar.UserSession)Session["SessionInformation"].CountID = cBox.SelectedValue;
It seems like the root of your question is actually about casting.
I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.
I have got several classes looking like the one below, and I need to do some checks in the get method and custom set methods. Adding the code in each get and set method makes everything look really messed up.
Is there a way I can override the get and set methods for all properties in an entire class?
public class Test
{
private DataRow _dr;
public Test()
{
_dr = GetData();
}
public string Name
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)] = value;
}
}
public string Description
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)] = value;
}
}
public string DescriptionUrl
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)]= value;
}
}
private void VerifyAccess(string propertyname, string classname)
{
//some code to verify that the current user has access to update the property
//Throw exception
}
private DataRow GetData()
{
//Some code to pull the data from the database
}
}
I think what you need is a Proxy on your class, read about Proxy Pattern and Dynamic Proxies
Not directly, there isn't a way to do it with just a compiler. You'd have to generate your entire binary file, then post-process it with some external tool.
This post describes a somewhat similar issue; I hope it helps.
There's a variety of ways to do it.
One would be to create a proxy class (mentioned before), but that would require a lot of refactoring on your behalf.
Another way is with aspects. These do exactly what you're after (insert code based on a pre-requisite.. i.e. all get methods in a class that inherit from x). I ran into a similar problem (actually the exact same problem - checking for security on method calls), and couldn't find cheap/free aspect software that fulfilled my needs.
So, I decided to use Mono-Cecil to inject code before function calls.
If you're interested (it gets a bit messy dealing with IL codes) I can post an old copy of the source
You should extract common code to separate get/set methods, after that you'll be able to add common logic to your properties. By the way, I would do such extraction anyway to avoid copy/paste in the code.
Smth like this:
public string Name
{
get { return GetProperty(MethodBase.GetCurrentMethod()); }
set
{
SetProperty(MethodBase.GetCurrentMethod(), value);
}
}
private string GetProperty(MethodBase method)
{
return _dr[method.Name.Substring(4)].ToString();
}
private void SetProperty(MethodBase method, string value)
{
string methodName = method.Name.Substring(4);
VerifyAccess(methodName , this.GetType().Name);
_dr[methodName] = value;
}
This can be done with indirect value access, e.g. obj.PropA.Value = obj.PropB.Value + 1 -- you can even keep strong typing information. It can be implemented with either attributes or direct-instantiation.
// attribute -- bind later in central spot with annotation application
[MyCustomProp(4)] CustProp<int> Age;
// direct -- explicit binding, could also post-process dynamically
CustProp<int> Age = new CustProp<int>(4, this);
Alternatively, perhaps using a template system such as TT4 may be a viable approach.
However, don't forget "KISS" :-)
I would love for someone to give a better answer for this.
I'm looking for an answer now… best idea I have had would be to define all the properties you want to have be validated as a generic class. For example:
public class Foo {
public String Name {
get{ return _Name.value; }
set{ _Name.value = value; }
}
private Proxy<String> _Name;
static void main(String[] args) {
Foo f = new Foo();
//will go through the logic in Proxy.
f.Name = "test";
String s = f.Name;
}
}
public class Proxy<T> {
public T value {
get {
//logic here
return _this;
} set {
//logic here
_this = value;
}
}
private T _this;
}
I’m trying to manage multiple models in a messaging based system. Each model might have values that are dependent on other models. For example:
public class V2Model : BaseModel
{
private int mSomeVal;
private byte mSomeByte;
// …
// Update mSomeByte based on multiple models values
public void SetMultipleDependecyValue(int someIntFromModel1, short someShawteeyFromModel3)
{
mSomeByte = Convert.ToByte((someShawteeyFromModel3 / someIntFromModel1) + mSomeVal);
}
}
I would also like to use the MVC pattern, but instead of passing a Model instance, I thought I would pass in a ‘Repository’ instance. The ‘Repository’ instance would act as a manager for handling all the Model instances. The result would look something like this:
public class V1Controller<ViewType, ModelType>
where ViewType : IV1View
where ModelType : BaseModel
{
ViewType mView;
BaseRepository mBaseRep;
public V1Controller(ViewType view, BaseRepository rep)
{
mView = view;
mBaseRep = rep;
mBaseRep.GetModel<ModelType>().PropertyChanged += new PropertyChangedEventHandler(V1ModelPropertyChanged);
}
void V1ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SomeVal":
// Update the view
int some_val = mBaseRep.GetModel<ModelType>().SomeVal;
mView.HexSomeValue = some_val;
// Oh BTW, we know V2Model's value depends on this... update it with V1Model and V3Model's values
short some_short = mBaseRep.GetModel<V3Model>().SomeShawteey;
mBaseRep.GetModel<V2Model>().SetMultipleDependecyValue(some_val, some_short);
break;
}
}
public void UpdateVal(int someValue)
{
mBaseRep.GetModel<ModelType>().SomeVal = someValue;
}
}
In this situation, if V1Model’s property changed, in V1ModelPropertyChanged, I would know the dependency on V2Model’s object, and update it with the appropriate values. Is there a better way of handling this interdependent model scheme, or would this be an acceptable solution? I am not really looking for anything 3rd party.
If you want to handle this elegantly, you're going to need to have some component track the dependencies between the models. When a property changes, you would iterate over all of the dependencies for that property and then update them appropriately.
Perhaps your BaseRepository might hold a reference to a DependencyManager class. That class would have to have a list of all properties which depend on one another.
A simple implementation might look like this:
class PropertyDescriptor
{
public Type ModelType { get; set; }
public string Property { get; set; }
}
class DependencyManager
{
private Dictionary<PropertyDescriptor, List<PropertyDescriptor>> _dependencies = new Dictionary<PropertyDescriptor, List<PropertyDescriptor>>();
public void RegisterDependency(PropertyDescriptor property, PropertyDescriptor dependentProperty)
{
if (!_dependencies.ContainsKey(property))
{
_dependencies.Add(property, new List<PropertyDescriptor>());
}
_dependencies[property].Add(dependentProperty);
}
public IEnumerable<PropertyDescriptor> GetDependentProperties(PropertyDescriptor property)
{
if (!_dependencies.ContainsKey(property))
{
yield break;
}
else
{
foreach (PropertyDescriptor p in _dependencies[property])
{
yield return p;
}
}
}
}
Then when you detect a property change, you can query the DependencyManager for what else needs to change. But be careful to check for circular dependencies when you cascade!
Maybe I'm missing something, but isn't this what the observer pattern is for? If you set up the models as observers of each other (i.e., with delegates or events), then the controller should be able to remain blissfully ignorant of the dependencies.