using static slideshowextender method, for multiple users - c#

I am basically trying to display a set of images stored on a webserver to users via Ajax SlideShowExtender.
I am just wondering how best to approach this, since the function it uses to retrieve the images to display, is a static method. But this site can be used concurrently by 3 different accounts, each of which will have their own set of images to display.
I have always stayed away from static variables and methods whenever doing websites if possible when working with users and individual data.I am worried there will be issues with the slides returned to each account being mixed up due to method being static.
Now obviously I will have to test this fully and check if this will be happening, but is there a better approach to this, or a way to ensure each user is always working with their own set of slides? I was thinking of passing an argument to the method perhaps for each user, but not sure how I would use this to ensure each user gets correct images? See below for basic function that returns slides to slideshowextender:
[WebMethod]
[ScriptMethod]
public static Slide[] GetImages(int userID)
{
List<Slide> slides = new List<Slide>();
/* here there is a try catch to read all images from specific directory and add to slides[] */
return slides.ToArray()
}

Related

REST API different resources for GET and POST/PUT?

I'm currently in the process of designing as RESTful of an API as I can using Microsoft's Web API 2 in C#. What I'm struggling on is how best to represent resources or the proper way to do it where the GET call and POST/PUT are very different.
For example say I have something calls states that have an id, name, status, etc., these can be assigned to a document. So I have a route like this /documents/{id}/states/ . If I call a GET here I need to get the full list of all assigned states including their id, name, etc.
However, in order to change which states are assigned to the document I simply need to pass the id. I cannot do this individually, it must be an array that gets sent up since users may be interacting with hundreds or thousands at a time.
So in this case I have a few issues. I don't even know if POST or PUT is correct here, and second whichever one it is can I just take in an array of integers?
In your case, I would suggest PUT is the method you would be wanting to use, as you know the location of the resource that you are updating. For more info, see here: http://restcookbook.com/HTTP%20Methods/put-vs-post/
In ASP.NET Web API 2 you can use the [FromBody] parameter attribute, so that your method signature would be:
public void UpdateStates(int id, [FromBody]List<int> states) {}
More info on parameter attributes can be found here: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Static variable causing concurrency issue in mvc

We developing Web Application using mvc4. In many scenario we will get value from user in First Page/View which we need to keep in some varaiable until user reach Final Page/View. He/She may pass 4-5 views to reach final view from first view.
To keep Value in MVC. We had 3 ways.
1. Global Variable - But if i assign value in one action method. the value will be reset in another action method. So we dropped it.
2.Session - But we need to keep more then 5 values in each session. So we dropped it.
3.Static Varibale - Which works like charm. but in Multiple user it caused concurrency issue.
Is any other ways in mvc to keep values? please guide me.
Static variables will persist for the life of application domain, that is why you are seeing the concurrency issues with multiple users.
See: Static Variables and their implications in ASP.Net websites
There shouldn't be any problem in storing five values in a session. You can have List<T> and store that in session. Like:
List<string> someValues = new List<string> {"A","B","C","D", "E",};
HttpContext.Current.Session["userValues"] = someValues;
To retrieve it:
var someValues = HttpContext.Current.Session["userValues"] as List<string>;
if(someValues != null)
{
// found
}
The only thing you should consider is the size of data. Sessions are stored at server level for each user, storing too much data could cause a problem, though it depends on your configuration.
You may also see: What is ViewData, ViewBag and TempData? – MVC options for passing data between current and subsequent request

c# static Data Dictionary lingering when source data changes - even across IIS users

I have an online store and the software is highly customized but not completely ours. We sell tours and some of them have reservations so I added a calendar to let them pick the date/time they want. Originally each cal_SelectionChanged() call was looking stuff up from the store database and that was, of course, horribly slow. I wanted to use a Data Dictionary to get the information once and use it whenever needed.
I have this class:
public partial class ConLib_Custom_BuyTourProductDialog : System.Web.UI.UserControl
and this declared inside that class.
static Dictionary<string, string> CustomFieldDict = new Dictionary<string, string>();
I also have a function to load all the bits from a database that I'll need on my page. My plan was to call this on Page_Load() and just access the info when needed.
protected void LoadCustomFieldDictionary()
{
string _sku = _Product.Sku.Trim().ToLower();
if (CustomFieldDict.ContainsKey("Sku"))
{
// is the dictionary entry for *this* sku?
if (CustomFieldDict["Sku"] == _sku)
{
return; // already have this one.
}
}
CustomFieldDict["Sku"] = _sku;
CustomFieldDict["EventId"] = TTAUtils.GetCustomFieldValue(_Product, "EventId");
CustomFieldDict["ResEventTypeId"] = TTAUtils.GetCustomFieldValue(_Product, "ResEventTypeId");
etc.
}
Then my boss loaded a page - ok, everything was fine - and changed one of the bits of data in the database to point to a different, wrong, ResEventTypeId. Reload the page and it has the new data. He changed it back to the original and it was "stuck" on the wrong information. I loaded a browser on my iPad and went there and it fed me the wrong info as well.
It seems that the server is caching that DataDictionary and even if we change the database all visitors, even in other sessions, get this cached wrong info.
Do you think this assessment is right?
What's the proper way to do this so that a visitor changing dates gets some kind of cached lookup speed and yet another browser gets a fresh set from the database?
How do I make it "forget" what it thinks it knows and accept the new info until I fix it? Reset IIS?
Thankfully this is on a dev server and not my live store!
Thanks for your help. I've learned a lot about C# and .NET but it's shade-tree-mechanic type stuff and I lack the formal training that is out there and would really help in situations like these. Any help is appreciated!
For anyone coming by at a later time:
What Jonesy said is very true - statics are scary. I found out from one site (link to a link from his link) that statics like this are sticky to the Application Pool level so any other browser would get the "wrong" information.
For my situation I decided to use ViewState to store the info since it was small and my current V.S. isn't very large already. Beware doing this for large amounts of data but in my case it was the best.

Session instead of viewsate

I have found many questions here about storing values in viewstate, but haven't found a good answer.
I have a situation when i retrieve large amount of data from database. Then i filter and manipulate the data according to my needs (so it is a preety heavy process). Then I put the result inside a list of custom class. For example lets say this class will be Person
List<Person> persons = new List<Person>();
private void FillPersons()
{
//Call to webservice
persons = ws.GetPersonsList();
//Do all kind of custom filtering
//Manipulate the data
}
Now the whole FillPersons() method is a heavy process that returns pretty small amount of data. And unfortunately it can't be moved to SQL and the heaviness is in the process, but that is not the point.
The point is that i need to reuse this data on the page between post backs.
Right now in order to spare the additional call to FillPersons() I mark Person class as serializeable and store the list in the viewstate, that works fine except the fact that the page becomes 1mb size because of the viewstate. According to what i have read, it is not so acceptable approach i.e. it is not secure and it blows the source code making the page heavy etc. (second is what most concerns me)
So it leaves me with a session. However session is persisted not only between postbacks, but much after it, even when user leaves the page. Or worst- the session will end before user decide to postback. So finding the best time span for session lifetime is mission impossible.
My question is what is the best practice to reuse "datasets" between postbacks?
What you guys do in such cases?
Thanks.
PS: hidden fields etc. is not an option.
You can store this kind of data in the Cache. It is application wide, so depending on what you add use the key accordingly.
var key = UserID + "_personList";
Cache.Add(key, personList, null,
DateTime.Now.AddSeconds(60),
Cache.NoSlidingExpiration,
CacheItemPriority.High,
null);
Note that you can never assume that the data is in the cache (it might have been flushed) so always check if it returns null and than refill it.
Viewstate is not a good way of storing large objects. As you mentioned your page size will get bigger and every postback will take lots of time.
I would suggest using cache. By using cache your list wont be saved there till end of session and you can set how much time it should be stored there. For caching you may use HttpCache or some distibuted caching system like AppFabric or MemCached . This nuget package will help using these cache systems.
this link will help how to configure AppFabric.
I should edit with some code to make it more helpful.
https://bitbucket.org/glav/cacheadapter/wiki/Home
var cacheProvider = AppServices.Cache; // will pick cachadapter using web.config ( can be Http, Memory, AppFabric or MemCached)
var data1 = cacheProvider.Get<SomeData>("cache-key", DateTime.Now.AddSeconds(3), () =>
{
// This is the anonymous function which gets called if the data is not in the cache.
// This method is executed and whatever is returned, is added to the cache with the
// passed in expiry time.
Console.WriteLine("... => Adding data to the cache... 1st call");
var someData = new SomeData() { SomeText = "cache example1", SomeNumber = 1 };
return someData;
});
Other than a cache (good idea by Magnus), the only other way I can think of is to keep the results of your heavy operation stored in the database server.
You mention that it takes a lot of time to retrieve the data. Once done, store it in a purposely established table with some type of access key. Give that key to the browser and use it for pulling what pieces you need back out.
Of course, without knowing the full architecture it's really hard to give a solution. So, in order of preference:
Store it back in the database with a unique key for this user.
Store it in a remote cache
Store it in a local cache
Under no circumstance would I store it in the page (viewstate), cookie (sounds too big anyway), or in session.
Have you considered using ASP.NET caching?
You should choose a key that will suite your exact needs and you will have your data stored in the server memory. But keep in mind cache is application specific and is valid for all users.
If the data you process is not often changed, the processing algorithm doesn't depend on user specific settings and it is not critical to always have the latest data maybe this is the best option I can think of.
Store your filtered collection on disk in a file. Give the file the same name as a key you can store in viewstate. Use that key to retrieve the file on postbacks. In order to keep the file system from filling up, have two folders. Alternate the days for which folder you save the files to. That way you can wipe out the contents of the folder that is not being used that day. This method has extremely good performance, and can scale with a web farm if your folder locations are identified by a network path.
I think personlist is a shared object. Does everyone use the same list? You can store on Application.
Application["PersonList"] =persons;
persons = (List<"Person">)Application["PersonList"]
Or you can Store on Static class.
public static class PersonList { public static List<"Person"> Get {get;set;} }
You should write this code to Application_Start on Global.asax file
PersonList.Get = ws.GetPersonsList();
And you can get List by using this code
persons = PersonList.Get;

Data Access Library: What to return if access isn't allowed or data isn't found?

I'm building a DAL for a widget-based reporting application, its been designed in such a way that users pick, configure and deploy reporting 'widgets' to their home screens. Widgets can report across various kinds of company data - sites, brands, employees and so on.
Whilst all users can access all the widgets/reports, all users are not authorised to access all data. If I work for Company-A I can't view sales reports for Company-B or staff attendance data for a salesman at Company-C, however I can configure such a report and add it to my 'dashboard'.
At runtime, an intermediate 'DataService' class has the job of checking the user's credentials and, if access is permitted, returning the appropriate object collection to the client.
On the initial build I just returned an empty List if access to the data was not allowed, but this is also what I do if no data is returned by the report (which can happen). I'd like to show an 'Access Denied' message on the front end if the user isn't authorised to view the data but obviously if all I get back in either eventuality is an empty collection its impossible to know if this was because of insufficients rights or just no data.
I'd be grateful if you could suggest a way of coding around this, my first thought was to move the credential-checking into another object which in turn calls the data access class but time constraints mean this isn't an option.
The only thing I can think of, which goes against everything I've ever learnt, is to throw a custom exception e.g. InsufficientApplicationPrivilegeException if access isn't granted, but this smells bad.
Thanks for reading.
I think you have a couple of options. One is to make a composite object that your data service class returns. The composite object looks something like this: -
class DataResult<T>
{
IEnumerable<T> Data;
Result ServiceResult;
}
ServiceResult contains metadata about the outcome of your service call - it could be an enum which contains e.g. Success, AuthenticationFailure etc. etc.. You can then switch on this in order to do different behaviour.
An alternative option might be to use the NullObject pattern that shows a single item of data in the view which instead of real data simply shows "Access Denied" for the display properties of the object. The advantage of this approach is that your front-end doesn't need to have any conditional logic etc.; however if you want to show a specific message box or similar rather than just displaying a dummy row of data in your widget, then this probably isn't appropriate.

Categories

Resources