Saving multiple values in a single session variable and then retrieve them - c#

I'm working on asp.net mvc3 application. I guess it's described somewhere but a fast search didn't help much and also I get very diverse opinions on using Session variables but still I have a little time to make a decision.
The problem is that I have a razor view where in image gallery images are shown and user that has permissions can delete one or many images. However I can't delete each image at the time the user click the button, instead I have to collect the id's of the images that have been "deleted" from the user (I remove the span tag which holds the image) but the actual deleting is perform by service and I have to pass the service all the data at once.
All this is inside Html.BeginForm so the data is collected on submit and before that I need a way to store those values somehow. Using sessions seems the easiest way by now. I tried something like this :
public void DeletePicture(long documentImageID)
{
if (documentImageID != null)
{
Session["imagesIdForDeleting"] = documentImageID;
}
}
But with a simple debug I can not figure out first - how at all I can access the documentImageID value from the Session["imagesIdForDeleting"]. I don't know if it's just matter of syntax or I'm trying to make the things less complicated than they are in real. Also - I'm not sure if making something like this I'm actually saving all the values or I rewrite the previous value and always have only one value stored in the session variable. Anyways, Any help how to implement this right would be appreciated.

You can store list in Session.
e.g.
public void DeletePicture(long documentImageID)
{
if(Session["imagesIdForDeleting"] == null)
{
Session["imagesIdForDeleting"] = new List<long>();
}
if (documentImageID != null)
{
var list = (List<long >)Session["imagesIdForDeleting"];
list.Add(documentImageID);
}
}

I'm not sure if making something like this I'm actually saving all the
values or I rewrite the previous value and always have only one value
stored in the session variable.
Yes you are right about overwriting the stored value.
Use a typed list to store the images and put it in session.
public void DeletePicture(long documentImageID)
{
if (documentImageID != null)
{
if(Session["imagesIdForDeleting"]) == null
{
Session["imagesIdForDeleting"] = new List<long>();
}
((List<long>)Session["imagesIdForDeleting"]).Add( documentImageID);
}
}

Related

Xamarin Pass Entry Value to new page from old

Hi i have a page where i get the user to fill out their fast name and last name and then when they hit the next button it performs an:
await Navigation.PushModalAsync(new VisitorHSAgreement());
to the next page, what I want to do is bring them values to display in a label on the next page I have currently tried this but it's coming back null can anybody help me.
public string VisitorFirstName { get; set; }
public string VisitorLastName { get; set; }
var visitorPage = new VisitorPage();
VisitorFirstName = visitorPage.FindByName<Entry>("FirstNameEntry").Text;
When on VisitorPage, there is an instance of the class VisitorPage. This instance contains controls, which are instances, too, and might have values set in their properties.
Now you navigating to VisitorHSAgreement and try to get a value from the VisitorPage by creating a new object of this class. Each object of this class comes with its own values and the controls are newly created. Unless you create some static field in VisitorPage you will never be able to access the values that are set in the first instance from the new instance. You should really read up on basic concepts of OOP, because this is really OOP 101.
I'd suggest to use MVVM along with the Prism library, this will really make your Xamarin.Forms life easier. Anyway, if you can't or don't want to at the moment (it's up to you in the end), there is still a solution. Since your properties are public, you can set them before navigating to VisitorHSAgreement
var page = new VisitorHSAgreement()
{
VisitorFirstName = FirstNameEntry.Text,
VisitorLastName = LastNameEntry.Text
};
await Navigation.PushModalAsync(page);
You need to learn how to work with Object Oriented programming.
As mentioned in the previous answer, you are trying to access empty values from a recently created object (which will obviously empty). While what you need to do is assign the values to the object you want to send, and then send that object (data filled in) to the page you want to use it.
Then in your page, receive that object sent from the previous page and explore its properties to obtain your values.

How to maintain the values in view when i do postback in MVC

I have some controls in my page, when the page load first time the values are getting from database and placed in corresponding controls. When i click the another button again it will go to the controller and get the value from the database and bind the gridview. I have three class in my model, second and third class wrapped in first class. when i bind the second class in gridview, that time first class comes null so all the values are becoming null and bind the gridview only. How to solve this.
Again HTTP is stateless, unless you store your current model in a persistence medium like session, it will get lost in post back!
if I understood your question right !
when you bind your classes for the First Time , put them in a Session var then return it to the view ,
then when you post the second time when you click the other button, make sure to retrieve the session var in the actionmethod and then assign the new values to the class inside this session var, instead of just returning the new ones thinking that old ones are still there.
If I understand what you are asking then you can store it in TempData. TempData will persist until the next request.
public class YourView
{
public ActionResult Index()
{
string firstName = "Stephen";
TempData["FirstName"] = firstName;
return View();
}
public void ButtonClicked()
{
string firstName = (string)TempData["FirstName"];
}
}
Note though that temp data only lasts until the next request. So for this to work, after your view was loaded then the next call would have to be the ButtonClicked call.
The controller is stateless so if you need to persist something longer you have to make it kinda hackish and really ugly like this TempData["FirstName"] = TempData["FirstName"] in every spot that your controller will be called until you need to use that value. Like I said I don't recommend that (or for that case using Session) but if you needed to, then that's the safest way, in my opinion.

shared asp.net object as static or cache

What is the best method of storing a shared object in asp.net? It will get called multiple times per request on every request. Ive been using these two methods but Id like to know if there is a better way. I refresh this object once an hour.
public static List<ResourceObject> SharedResources = new List<ResourceObject>()
//OR
public static List<ResourceObject> SharedResources
{
get
{
List<ResourceObject> _sharedResources = HttpContext.Current.Cache["RedirectRoutes"] as List<ResourceObject>;
if (_sharedResources == null)
{
_sharedResources = LoadNewSharedResource();
HttpContext.Current.Cache["RedirectRoutes"] = _sharedResources;
}
return _redirectRoutes;
}
set
{
HttpContext.Current.Cache["RedirectRoutes"] = value;
}
}
If your object is changing frequently (i.e. hourly as you mentioned) then you'll be best to use the cache as it will be able to take care of flushing for you (assuming you pass the correct parameters when adding the value to the cache). If you use a static value it will not be cleared out every hour automatically so you'd need to implement the check yourself.
If this is, as it seems, an object that needs to persist across requests, then this is a perfectly good and reasonable way to achieve it. You may want to put the cached version in a local variable if it is being accessed multiple times within one call, to save retrieving it from the cache each time.
Is there a specific issue with caching it like that that you are concerned about?

Where to store data in order to avoid database hitting?

I am using webmethod which fetches data from database & storing it in a static variable so that next time it will not hit the database becoz the data is being accessed frequently. Creating static variable doesn't seem to be a proper solution what is an alernative to this scenario.
e.g
public static List<SupplierGridData> lstFullSupplierData;
public static List<SupplierGridData> GetProductData()
{
if (lstFullSupplierData == null)
{
//first time get data from database
lstFullSupplierData = new List<SupplierGridData>();
lstFullSupplierData = new POProcess().GetInquiryDetails();
}
else
{
//use lstFullSupplierData which holds data
}
}
What you want is caching:
http://msdn.microsoft.com/en-us/library/xsbfdd8c.aspx
More specifically, caching data:
http://msdn.microsoft.com/en-us/library/6hbbsfk6.aspx
There is also Session State:
http://msdn.microsoft.com/en-us/library/ms972429.aspx
This comes in the per-application and per-user guise. And you can also change the backing store of session state.
The easiest solution to this could be hitting the db once if(!this.IsPostBack) then burying that stuff in the viewstate of the page if it's not too much stuff (assuming you don't need to carry across other pages). Otherwise session or cache will do as other people are suggesting.
You need to store your data in session in order to not hit the database again.
http://msdn.microsoft.com/en-us/library/ms178581.aspx

ASP C# How to program neat GUI code

For about a few months i'm programming ASP C#. I always program a lot code in the events and in the load event i check the querystring for valid data. This is some sample code i have in one of my projects:
protected void Page_Load(object sender, EventArgs e)
{
if (Controller.Manual == null)
{
Response.Redirect("login.aspx");
}
lblLocation.Text = "<a href='viewdocument.aspx'>" + Controller.Manual.Title + "</a>";
if (Request.QueryString["gchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
{
genchap = Convert.ToInt32(Request.QueryString["gchap"]);
FillGeneralList();
SetChapterTitle();
}
}
if (Request.QueryString["qchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["qchap"].ToString()))
{
qualchap = Convert.ToInt32(Request.QueryString["qchap"]);
FillQualityList();
SetChapterTitle();
}
}
// Check document Id is set (did)
if (Request.QueryString["did"] != null)
{
if (Controller.IsNumeric(Request.QueryString["did"].ToString()))
{
docId = Convert.ToInt32(Request.QueryString["did"]);
DetermineView();
}
}
}
I know there must be a way to accomplish this on a more neat way. And this is just the load event. On other events, like click and onchange events i have similar code. I think this is spaghetti code and not well-arranged. So can you tell me how i can arrange my code?
EDIT:
What i want to know is, is there a more neat way to, let's say, fill a listbox? And where do i check whether a querystring value has valid data? Where do i check whether the (input/querystring) data is a number? And where should you put the code that validates the Querystring? Also in the load event?
I feel your pain with some of the organization issues with ASP.NET websites. I've had similar code to yours on several projects.
If you have the choice of your frameworks you might look into ASP.NET MVC. This allows you to have clear separation between the View (Html), the Controllers (All actions and business logic) and the Model (database). That way you have zero code in your codebehind files, it all stays nice and neat in controllers.
Try using TryParse (for example) and you can simplify all the code that looks like
xx.IsNumeric(Request.QueryString["qchap"].ToString())
and
Convert.ToInt32(Request.QueryString["gchap"]);
and reduce the number of calls to Request.QueryString variables
You could try something like
Original code
if (Request.QueryString["gchap"] != null)
{
if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
{
gchap = Convert.ToInt32(Request.QueryString["gchap"]);
FillGeneralList();
SetChapterTitle();
}
}
Suggestion
int? gchap; //nullable types thanks Richard :D
if (!int.TryParse(Request.QueryString["gchap"], out id)) {gchap = null};
if (gchap != null) {
FillGeneralList();
SetChapterTitle();
}
// you could make this neater with your own little method
Have a look at this post How do you test your Request.QueryString[] variables?
Try capturing the repetitive code in a separate function. (qchap / gchap)
e.g.:
qualchap = ConvertFillAndSet(Request.Querystring["qchap"]);
genchap = ConvertFillAndSet(Request.QueryString["gchap"]);
private int ConvertFillAndSet(string qrystring)
{
int numberToReturn = 0;
//if the conversion was ok -> true, else false
if (Int32.TryParse(qrystring,numberToReturn))
{
FillQualityList();
SetChapterTitle();
}
//returns 0 if tryparse didn't work
return numberToReturn;
}
Where to start. Unfortunately despite other comments, you're not really writing anything that is 'web forms' specific. So moving to MVC isn't going to magically make your code better.
1 Don't roll your own authentication: Use forms authentication unless you have a compelling reason not to. When using forms authentication, you don't need to write code on every page to check that you're logged in. The framework handles that for you.
2 Learn to use the server controls:
Also as others write you shouldn't be writing html in code, especially for something so trivial. Web forms doesn't make you do this either.
<!-- this is in MyPage.aspx -->
<asp:HyperLink id="viewLink" runat="server" />
// in the code-behind file MyPage.aspx.cs
viewLink.NavigateUrl = "~/viewdocument.aspx";
viewLink.Text = Controller.Title;
If you're going to stick with web forms, you need to get familiar with the ASP.Net Page life-cycle
3 Your code is in need of refactoring. No matter if it's web forms, php, or MVC. Here are some basic refactorings, and none of this is really .net specific. I'll walk through these in small steps.
// this may be a good candidate for an extension method
int? ConvertNullable(string nullableInt) {
if( string.IsNullOrEmpty(nullableInt) )
return null;
int value;
if( Int32.TryParse(nullableInt, out value) )
return value;
return null;
}
which then allows you to write.
int genchap? = ConvertNullable(Request.QueryString["gchap"]);
int qualchap? = ConvertNullable(Request.QueryString["qualchap"]);
int docId? = ConvertNullable(Request.QueryString["did"]);
FillQualityList(genchap,qualchap);
SetChapterTitle(genchap,qualchap);
DetermineView(docId);
but passing a lot of primitives around is a hassle and prone to errors, so sometimes we make a small class to encapsulate the data, in this case the page initialization information.
class ChapterView
{
public int? GenChapter {get; set;}
public int? QualChapter {get; set;}
public int? DocumentId {get; set;}
}
private ChapterView GetChapterView()
{
return new ChapterView
{
GenChapter = ConvertNullable(Request.QueryString["gchap"]),
QualChapter = ConvertNullable(Request.QueryString["qualchap"]),
DocumentId = ConvertNullable(Request.QueryString["did"])
}
}
Note that I've no idea what GenChap and QualChap are, but they're a bit terse and you could complete the refactoring to make them more readable in code. But even without better names, we now have more readable code.
ChapterView chapterView = GetChapterView();
FillQualityList(chapterView);
SetChapterTitle(chapterView);
DetermineView(chapterView);
And finally you may determine that you don't really need to call this every time the page executes to read from the query string. If you've read up on the Asp.Net Page LifeCycle you know that events may change GenChapter or something else that affects how the page is rendered. You may find it better to set up the view in the PreRender instead of calling FillQualityList over and over again.
ChapterView chapterView;
Page_Load()
{
if( !IsPostback )
{
ChapterView chapterView = GetChapterView();
}
else
{
chapterView = (ChapterView) ViewState["chapterview"];
}
}
NextChapter_Click()
{
chaperView.NextChapter();
}
Page_PreRender()
{
FillQualityList(chapterView);
SetChapterTitle(chapterView);
DetermineView(chapterView);}
// make sure class is marked [Serializable]
ViewState["chapterview"] = chapterView;
}
you should follow layered approach. ie: put all your data access code in data access layer, put all your business logic (which also includes validations) in your business layer, put all your model code in your business object layer
and finally for ui - try to never generate html mark up from within the code as far as possible. also, always create a root class for your aspx pages where it has common methods already implemented. then subclass this root class for every other aspx pages
if you are going to hardcode html markup within your c# code - i can assure you this would always result in a lot of chaos (based on my own experience)
but there are situations where you simply cant avoid it. for such cases - this is what i do - i get rid of the code behind and simply put that code in my aspx / ascx file itself. that way when i have to change my ui based on never ending client requests, i dont have to recompile my code - i simply replace my aspx / ascx files on the staging / production server.
you know how clients are : hmmm can u make the black strip look a bit like gray, can u increase the spacing between lines, can u change the text of this hyper link... requests like these never seem to end :-)

Categories