Let's say I wish to store an instance of the following in Application State, to be accessed very often.
public class Example {
public string A;
public string B;
public bool C;
public int D;
// ...
}
I can't decide whether to store the whole class together as Application["Example"], or to store its properties individually as Application["ExampleA"] etc.
My thinking is that ((Example)Application["Example"]).A might have to copy the whole class into memory just to access one property - is that right? Or am I mistaken?
I would use a static global variable, slightly better performance, type safe and will make your code easier to read. For more info see...
ASP.NET Application state vs a Static object
you are right but....
you don't need to copy the whole object if you just need the value of one of its property.
Conceptually if we are talking about a value object(you don't need an identity or a particular object) you can store just the property.
If you need to know what is the value of the property for one particular object(imaging a user's password) you should store the whole object.
The application state is stored in memory anyway so I can't see a significant overhead with retrieving the class. I'm fairly sure, although could be wrong, that the classes wouldn't be serialised/deserialised with each request.
Related
Current project:
ASP.NET 4.5.2
MVC 5
EF 6
In all honesty, I have never made use of a mapper before, and while the ExpressMapper tutorial bounces across the high-altitude highlights, it makes several assumptions about knowledge that I don’t have.
So in no general order:
The product is supposed to have all its code centralized in one spot. Where is this spot? Where do I put it? The examples start out with,
public void MappingRegistration() {
Mapper.Register<Product,ProductViewModel>();
}
But I don’t know where to put this. Does it go into its own file or is it in another file, such as within App_Start?
If it is elsewhere in the project, do I create it under its own namespace?
If I have a viewModel that is filled in a different way than its dataModel is filled, how do I handle each type separately? As in, the data is pulled out of the DB and fills the viewModel with completely different conditional rules than how the data is pulled from the viewModel and inserted into or updated back to the database.
How do I bring in external conditionals that affect how the data and which data is inserted into the DB, such as the Role of the user, their UserId and UserName, and various project Settings? Depending on conditionals, some entries may end up with a null value instead of an actual value. How can I do business logic validation using these conditionals (User is actually updating his own record, by comparing their session UserId with the UserId stored in the DB)?
Right now I am doing a lot of manual mapping in the Models but this is problematic especially since the method I am using (to cut down on code in the controller) means that during an update I cannot examine an entry in the DB prior to updating it in the DB.
You can stick it anywhere you want - the only thing necessary is that it gets called in code, before you call Mapper.Map<Product,ProductViewModel>.
E.g.
public static void main()
{
Mapper.Register<Product,ProductViewModel>();
}
is functionally the same as
public static void main()
{
RegisterMapping();
}
public static void RegisterMapping()
{
Mapper.Register<Product,ProductViewModel>();
}
If you want to map one class member to another class member with a different name, you can specify it with Member mapping.
Mapper.Register<Product, ProductViewModel>()
.Member(dest => dest.efgh, src => src.abcd);
If you want to apply special conversion rules, you can specify that with a Function mapping - e.g. you want the price in the ProductViewModel to be 2x the price of the product :
Mapper.Register<Product, ProductViewModel>()
.Function(dest => dest.Price, src => src.Price*2);
Any customisation that you make to the mapping should be done at the time you register the mapping, and has to be done on a Member-by-Member basis AFAIK.
If there's anything else specific that you need help with, leave a comment.
Currently have a Factory class that features a GetSelector function, which returns a concrete implementation of ISelector. I have several different classes that implement ISelector and based on a setting I would like to receive the appropriate ISelector back.
public interface ISelector
{
string GetValue(string Params);
}
public class XmlSelector : ISelector
{
public string GetValue(string Params)
{
// open XML file and get value
}
}
public static class SelectorFactory
{
public static ISelector GetSelector()
{
return new XmlSelector(); // Needs changing to look at settings
}
}
My question is what is the best way to store the setting? I am aware of using AppSettings etc. but I'm not sure whether I want to have to store strings in the web.config and perform a switch on it - just seems to be really tightly coupled in that if a new implementation of ISelector is made, then the Factory would need to be changed. Is there any way of perhaps storing an assembly name and instantiating based on that?
Thanks,
Chris
It is hard to say, because I don't know the architecture of your particular project, but at a first glance what I would do is if the objects associated with ISelector can be decoupled from your web application, I would put these objects in a class library along with the factory. Your factory will need to be changed if you implement a new ISelector, but if you can decouple the whole ISelector family from your actual web application the depth of the refactoring you will have to do will be minimal compared to a monolithic architecture.
Personally, I tend to avoid AppSettings, web.config settings and the like for mission-critical design questions. Using the web.config as an example, I have seen applications where architectural data is stored for ease of configurability. The problem is that after compilation your web.config can be changed (that is the purpose of it after all) and if the implementation of your classes depends on very specific values being chosen, you are running a risk of a crash when someone inadvertently modifies the wrong value.
Like I said all this depends entirely on your application architecture, but my reflex would be to split out the components that could be subject to future modification into a class library. Loose coupling is your friend ;).
Instead of doing it in AppSettings, I think a better approach will be to create a separate XML file, which will only hold the mappings and from that file you can iterate through the mappings and return correct instance in GetSelector().
Say I have a page in my web application that lets a user update their contact information. Pretend in order to retrieve or save this information I have the following class:
public class User
{
DataAccesClass dataAccesClass = new DataAccesClass()
public string UserName {get;set;}
public string Address {get;set;}
public string EmailAddress {get;set;}
public User(){}
public static User GetUser(int userID)
{
User user = dataAccesClass.GetUser(userID); //
return user;
}
public void Save()
{
dataAccesClass.SaveUser(this);
}
}
Say that on my Page_Load event I create a new instance of my User class (wrapped in a !isPostBack). I then use it's public properties to populate text fields on said page in my web application. Now the question is... When the page is posted back, what is the correct way to rebuild this class to then save the updated information? Because the class was created on Page_Load !isPostBack event it is not available. What is the correct way to handle this? Should I store it in a Session? ViewState? Should I simply rebuild it every post back? The User class in this example is small so that might influence the correct way to do it but I'd like to be able to take the same approach for much larger and more complex classes. Also, would this class be considered an acceptable business object?
what is the correct way to rebuild this class to then save the updated information?
I would say the best practice would be do not rebuild the class on every postback. You should build the data on the first request, set values on controls, then let the viewstate on those controls persist the data.
If there is a potential for the data to need to be updated, tie re-generation of the object to an event indicating there is actual need to update.
Should I store it in a Session? ViewState? Should I simply rebuild it every post back?
Selecting whether to store the value in session or re-pull from the data layer should be based on the memory footprint of the object, the scalability requirements of the application, the costliness of the database operation, and the likelihood that the object will need to be accessed on any particular request. So I believe that is highly situational.
Also, would this class be considered an acceptable business object?
I don't have a lot of experience with BLL's but it looks like you're on the right track.
Unless profiling indicates otherwise, it's okay to just reconstruct the object with every request. You can also implement some kind of caching in your data access code. Your class is an acceptable business object.
Given that User object might have info you wouldn't want to expose through ViewState, it can be stored in Session.
This is the "standard" way of doing this in ASP.NET.
In the case of your example, reconstructing the object looks fine as it is small. But if you have a small object you inevitably store for a while, I would use session. If the object is large, I would directly use database or session with database connection.
Depending how complex you are thinking of getting a JavaScript framework called knockout.js might be a good fit. You could create a json object to bind to a jQuery template that would build the HTML depending on the object, it handles complex objects very well.
I have an ASP.NET MVC application. I have come to an idea of generating autoincremented values to be used as unique element ids. The question is, how can I have and work with a global variable which should be there for the duration of a request (page generation) but no longer?
I thought of using TempData for this shared variable and then just delete this key when the page is done. But then, where in code to purge this TempData key? Obviously it has to be some very last piece of code where the page has been rendered already.
Any input is highly appreciated.
EDIT: I have a number of HTML helpers that can be called from various views and partial views, so declaring a variable on a page and passing it to each helper is obviously not a good solution. I wish to just use the helpers and know they all are getting unique ids behind the scenes.
Okay, I have googled a little bit and found a solution on ASP.NET forums.
http://forums.asp.net/t/1401685.aspx
Obviously, I can use the HttpContext.Current.Items collection to have my little static variable for the duration of a request.
If all you need is to store a number, the resources that would take to manage its lifestyle would take a lot more than just having a one static integer and always reusing it.
Do not bother deleting the key after each request. Just use a static (I think this is shared in visual basic) integer, use and increment it every time you need a unique value. Also take its mod with a ridiculously high number each time to make sure it will not be reused in a single request and it will never overflow.
Why don't you define your integer variable at the top of the page view file?
Use it throughout the view rendering execution and at the end of it you can easily leave it as is. You don't have to explicitly destroy anything. Your variables live for the duration of request only. IIS is stateless service (if you subtract Session, Cache and Application variables) so it doesn't really remember anything explicitly.
I would imagine you could use the Application_BeginRequest and Application_EndRequest methods in global.asax.cs; Note I can't double check the method names currently, but I think they are close.
You could create a member variable in your controller which would be regenerated for each request:
public class ItemController : Controller
{
private int _UniqueID = 0;
public ActionResult Index()
{
foreach (var item in items)
{
item.UniqueID = _UniqueID++;
}
// etc...
}
I have an ASP.NET web application and I want to be able to take items from a master list and store them temporarliy into one of four other lists. The 'other' lists need to survive post backs so that more items can be added to them. What direction would you suggest going with?
I have thought of using a generic list stored in memory, temporarliy storing the items into the database and calling them back on PostBack, or storing them into the viewstate, but I have a feeling that there is some solution that I'm missing that might be easier or better.
Josh laid out the states pretty well. My recommendation for a smaller list like he said would be using Session state. Using the DB would be a little messy because you have to maintain those temp tables and worry about multi-session access to the tables. Likewise, cache have the same problem. Viewstate gives you this with extra client traffic and insecure data. So if you're talking less than a few thousand instances on a low traffic server, then session is likely fine.
To make session easier to work with (and you can do this with caching and application state as well) is setup a container object that manages the lists.
//To use it in your page, you can easily access it via:
ListManagerContext.Current.MasterList.Add(4);
[Serializable]
public class ListManagerContext
{
public List<int> MasterList { get; set; }
public List<int> SubList1 { get; set; }
public List<int> SubList2 { get; set; }
public List<int> SubList3 { get; set; }
/// <summary>
/// Key used for the list manager context session variable.
/// </summary>
public const string ListManagerContextKey = "ListManagerContext";
/// <summary>
/// Gets the current ListManagerContext for this session.
/// If none exists, it returns a brand new one.
/// </summary>
[XmlIgnore]
public static ListManagerContext Current
{
get
{
HttpContext context = HttpContext.Current;
if (context != null && context.Session != null)
{
ListManagerContext data = null;
if (context.Session[ListManagerContextKey] == null)
{
data = new ListManagerContext();
context.Session[ListManagerContextKey] = data;
}
else
data = context.Session[ListManagerContextKey]
as ListManagerContext;
return data;
}
throw new ApplicationException("
No session available for list manager context.");
}
}
}
The first thing I would suggest is to see if you can remove the need of keeping state across postbacks.
If you can't do so (and ViewState is not applicable for some reason like bandwidth limitations or requiring data preservation even without a postback from a server form), I suggest consider using Session. You can configure session state to use a SQL Server database backend whenever you want without worrying about changing source code.
The database Idea is likely a poor one (assuming you're not dealing with large amounts of data).
Perhaps your best method would be to store the main list in ViewState, and have the other lists be lists of indexes to the first list.
The lists should automatically store the values they have in the viewstate. If they don't, you probably need to turn the viewstate on for these controls.
If you manually want to make the data survive the round trip, you can either store them in the session or in the viewstate yourself. Technically the viewstate makes the most sense, but if there's a lot of data, it can make the viewstate very large and take a long time to do a round trip. The only issue with the session is you'll have to make sure you clear it once you leave the page.
Don't use the database, that's not what its for.
You could store the list in ViewState or Session and assign it to a property. Here's simple example using a generic list of string, but can be any serializable type.
private List<String> MyTempList
{
get{return Session["mylist"] as List<String>;}
set{Session["mylist"] = value;}
}
protected void Page_Load(object source, EventArgs e)
{
if(!IsPostBack)
{
MyTempList = new List<String>();
}
else
{
MyTempList.Add("Something");
}
}
All of those are options and all have pro's and cons:
Database:
Storing items in the database is a fairly easy and consistent option. You do have to worry about making a round trip call to the database, but at least you have a centralized location to story the data that will scale easily with your web load. However, if this is short lived data, then you will have to worry about cleaning up your database as it might begin to get unwieldy.
Session/Cache:
Session affords a quick solution for in memory storage, but scaling can become problematic if the amount of data is very large. The more information you store in memory the less capacity you have for concurrent users. Also, if you start to add multiple web servers, then you will have to look into some sort of session state server to make sure users don't spontaneously lose their session.
Cache has basically all the same pros/cons except that there is the additional complexity of having to make sure you expire cache items, and manage concurrency issues.
Again, these are both easy to implement solutions, but don't scale as well under heavy load, or large amounts of data.
ViewState:
Viewstate is also an easy to implement solution and gets the load off the server and into the client, but can result in longer load times for the end user. Also it is important to remember that ViewState can be hacked, so if security is a concern then you want to take extra precautions to ensure data integrity.
Conclusion:
All in all, figure out what you want to accomplish and choose the solution that best fits your needs. Shove it behind some abstraction layer like an interface so you can easily change the details later, and then you won't have to worry as much. It's all about knowing what will work best in your particular scenario.