asp.net webapp - is viewdata safe for local request variable? - c#

What is my need -I have a .net7.0 asp.net-webapp (razor). There are some parts of my cshtml that i want to customise based on per request which will be determined by c# corresponding PageModel class code.
What i did -
1 - using class static variables.Result - blunder. got to know they are same for all users so it would have broken site functionality.
2 - using cookies
Result - cookies can only be appended to response and read on request, so data can't be transferred within one request but it is good for transferring data across requests.
3 - Viewdata["name"]
Result - found good for my need. the data is available only for that request.
What i want to know -
1 - Does the data in viewdata get destroyed after request ends or it piles up in server's memory.
2 - Is it safe to use viewdata in this way. Is there anything i should keep in mind while using it so it can be secure, doesn't load the server and provides needed functionality.

You haven't actually given any details of what your need is, but in answer to the main question, ViewData is not stored across requests. It is a property of the PageModel, which is instantiated with each request and destroyed once the request has been processed and the response generated.
ViewData is used for passing data to views/pages. It is not strongly typed and can be error prone. For that reason, it is recommended to use public properties of the PageModel for passing data to views/pages. ViewData's primary use case is for passing data to weakly-typed Layout pages.
https://www.learnrazorpages.com/razor-pages/viewdata

Related

How to use the data from get request in a post request?

I’m kind of new to APIs and currently working on a project using the Spoonacular API. Im trying to build a meal planner website. At the moment, I’m working on the “Add To Meal Plan” feature which is a post method. To get the information for the post method, I think have to use a get method to retrieve recipe information from the API using a Recipe ID. I’m using TempData to store the information I get back from the get method so I can use it in my post method. Is this the most efficient way to be doing this? Or is it better to have my get and post requests be in the same method so I don’t have to store anything?
Currently, I’m using TempData to store the recipe information. It works but just not sure if this is the most efficient way to do this. I’m storing an object that I’ve serialized.
Using TempData is an acceptable approach for storing temporary data that needs to be passed from one request to another. It's part of the ASP.NET Core framework and provides a simple way to store values between multiple requests.
However, depending on your specific use case, there might be other ways to store this information that are more efficient. For example, if you want to store the recipe information for multiple users and persist it between sessions, you could consider using a database or a caching solution.
If the information you're storing is specific to a single user session, then TempData might be the best choice as it's relatively lightweight and easy to use.
In terms of combining the get and post requests into a single method, it's not necessary to do so. However, it might be more efficient in terms of network requests and server load if you can reduce the number of requests that need to be made to retrieve the required information.
Tell me if this helps :)

storing a js value from 1 ActionResult to use in another ActionResult

I've got a Controller, and in one of the ActionResults, there is a javascript value being returned that I can access via:
Request.QueryString["frequency"]
But I need to use that same variable in another ActionResult. How can I do this?
I know that I can't set a
string frequency = "";
at the top of the Controller, and then just set in the 1st ActionResult.
When you say ActionResult, I assume you mean your Action methods within the controller that return Actionresults? e.g.:
public class HomeController : Controller {
// GET: /Home/
public ActionResult Index() {
var freq = Request.QueryString["frequency"];
// ** Want to persist freq here **
HomeIndexViewModel model = FooLogic.BarIndex();
return View();
}
// GET: /Home/Detail
public ActionResult Detail() {
var freq = **Want to access freq here**;
HomeDetailViewModel model = FooLogic.BarDetail(freq);
return View();
}
}
As your question refers to ActionResult, this could be any kind of ActionResult - without knowing exactly what you are doing this answer outlines a general approach to choosing a state persistence store.
The key questions to ask yourself are:
who will need to see this value - just the user who's request generated the value, or other users as well,
if user specific, are they logged in, do they have a session?
how long will they need to be able to see it for (the next request only, or maybe the next day)
where will they expect to see it (just in the current browser, or in another session)
Your options for data persistence are many and varied, each fulfilling a slightly different role, though many overlap with others in their potential use (e.g. Session and TempData). I've listed many of them below, all of which could solve your problem depending on the exact scenario. The first two (View-persisted data or TempData) are most likely to be useful for you, but in the absence of more information others may actually be the ones you need.
There used to be at least Nine Options for Managing Persistent User State in ASP.NET, and many of those still apply in MVC.
ViewData and ViewBag
Available to: current user within the current request, but you can use it to "store state" within the generated html ready to be passed to future requests
Only relevant if your ActionResult is actually a View (rather than a redirect, or another ActionResult like a FileStreamResult)
Lets you pass data from the current controller action into the current view being generated meaning you can insert it into client side objects that could send it back in the next request such as:
hidden form fields;
query string parameters for the next request; or
javascript variables for ajax requests.
An example of this would be to pass your freq variable into the View for the Index method (for instance by using ViewBag.Frequency = freq;, and then use it with #Html.ActionLink. E.g.:
#Html.ActionLink("Click for the Next Action", "Detail", "Home",
new { frequency = ViewBag.Frequency }, null)
Your Detail action then becomes:
public ActionResult Detail(int frequency) { ...
Similar approaches would allow you to use the value in hidden form fields, or in javascript for future AJAX requests by setting a javascript variable using var freq = #Html.Raw(Viewbag.Frequency);, for instance.
Note: There is a school of thought (which I think is a good one) that you shouldn't be using these, instead you should create a strongly typed class (such as the above HomeIndexViewModel) for the Model for each view to allow you to better test your Controller Actions and Views.
Advantages of ViewData/ViewBag:
It maintains statelessness on your server, so that you don't have to worry about worker processes being recycled, the next request going to a different server in your web farm etc.
It is potentially "back button proof" as your "state" sits in the page that has been rendered
Disadvantages:
Only useful Actions that render html
Not all data should be back-button proof, some data should constantly evolve and therefore stored as server-side state (e.g. a page hit count)
TempData
Available to: Current User, within this and the next request
By default (in MVC 4) this is implemented by SessionStateTempDataProvider (see the documentation)
It is really meant to be used when your ActionResult is a redirect to another Action, that way you know the exact scope and lifetime of the data you have stored.
Ostensibly this is designed to do exactly what you want, but there are considerations.
It relies on session state, so works for web farm and web garden scenarios only if you have configured Session state appropriately.
Session state may also not persist between worker process recycles depending on your setup.
You also have to worry about what happens in a "back button" or F5 scenario as the data may not be available a second time.
Session
Available to: Current User, within the current session for them. Scope also depends on how you have configured session state (e.g. to be local to the application domain, or database backed and available across the web farm)
This has all the same considerations as TempData, but you choose when to delete the value from the Session. It is really intended for general information relevant to the current session (e.g. a simple shopping cart that the user wouldn't expect to see if they close and reopen the browser, or visit the site on their mobile phone later on).
Cache
Available to: All Users, but only within the current application domain (so beware worker process recycling, web farms, web gardens etc.)
You can access this through the HttpContext property of your Controller. E.g.:
HttpContext.Cache["Frequency"] = freq;
Cookies
Available to: Current user, but only from the browser they used for the original request
Cookies are often overlooked as state persistence - but they are very useful for some kinds of data. Remember that if the user expects to see data associated with a user identity, then the cookie won't help if they log in on another computer, use an Incognito/Private browser session etc.
Database
Available to: All users, or just the current user, for as long or short a time as you like - you choose.
Databases are the daddy of state persistence. Your application code should be viewed as volatile, and able to deal with restarts, web farm scenarios etc. etc. If you want to store data, use a database. By "Database" I mean a data persistence medium in any form, from SQL Server to Redis, Azure file storage, Azure table storage, Amazon S3 etc.
Other options
There are other options, they are not commonly as commonly used though. For instance, you can implement your own caching (example here), or use ...
Static or singleton classes
Available to: all users, all requests to that worker process on that server
Data will persist within a single worker process only (so this has implications for web farms and web gardens), and only until the asp worker process restarts
Thread-safety is still a concern, but at least you can encapsulate thread-safety logic within that class
Very rarely useful due to the coupling to the lifetime of the worker process, and to the single server
What not to use
Controller class fields (instance)
Available to: current user, current request only
(Disclaimer: I believe that a new Controller is created for each request in all versions of MVC, but if that is not the case then you would never use these to store state)
Theoretically you'll never use these (unless this is a 10-minute application for a demo to your colleagues):
As instance fields on a class persist only for the duration of the class (therefore the duration of the current request) if you want to store state (data) for the request you should be using variables within your Action method to better convey intent/manage scope of the objects/values.
So if you are using instance fields in your controller, you are probably sharing data for controller methods you are calling from your Action.
This means you are probably using your controller to enact business logic.
Current best practice dictates that Controllers should be a collection of Actions that call business logic (including any generation of view models), (thin, not fat, controllers).
Ergo: Controller class instance fields indicate you should restructure your code
The times you need instance fields on a controller are when providing common services to all actions, such as IoC interfaces, but these are not storing state within or across requests.
Controller class fields (static)
Available to: all users, all requests to that worker process on that server
Not a good idea - static fields will be available to all users on all threads, so you have to worry about thread-safety. There are better state stores available out of the box if you want to share data between all users, such as Cache
HTTP is stateless, every request has it's own state and Controller instance.
You can use TempData which use Session but delete the value after you read it.

How do you pass "expensive" data from page to page using ASP.NET MVC 3?

I am doing my first ASP.NET MVC project. (In fact, for the record, this is my first production website of any kind).
This is a mobile web page targeting HTML 5.
This page looks up some "expensive" information. First it uses the html 5 geocoding feature to get the customers latlong from their browser.
I pass that information to a controller. That controller fills in the City and State (into a location model) using the Google Maps API and then uses it in the view.
So this data is expensive in two ways, first it takes time to look it up and second, in the case of the Google API, it is literally not free in that Google limits the number of calls that can be made per day.
I understand that MVC is designed to "embrace" the web including the fact that http is a stateless protocol.
Nevertheless, I would like to avoid having to fetch this expensive data on every page load for every endpoint that needs it. Furthermore, one other piece of state that I would like to keep track is the fact that the data has already been fetched.
What is the best way / best practice for achieving this on an MVC 3 web application? Since my model for location has 4 data point (lat long city state) and there is a fifth data point (data retrieved) I would really like to avoid using querystrings to do this or a route for all of those data points?
I am sure this is a common need but I honestly don't know how to tackle it. Any help will be appreciated.
Seth
It Seems to me that you would like to cache the API call to google.
http://msdn.microsoft.com/en-us/library/18c1wd61(v=vs.71).aspx
You can store the object you got from google in cache and call it on the new controller event. you could also create another object that has the object from google and a bool that indicates if you have fetched the data or not.
It seem to me that the Cache would be your best bet.
You can store it in session state if it is available in your case instead of passing between pages.
Since this is "expensive" data, but still not to be persisted for a long time, you may:
use Session state
put the data in the Cache and either
set a cookie to enable the retrieval of the "expensive" data from cache
use a cache key which is unique to each query (lat long city state ?)
store the data ("data retrieved") on the client (since you do not seem to persist it on the server side)
My personal preference would be server side cache with a unique key.
Store expensive data to the cache, and build cache ID by parameters you send to google, cache id should be unique for every distinct place
Another option would be html5 storage. You will want to check to see if your target browsers support it though. The advantage to this approach is that the server does not have keep track of this data in session or a database - in fact the server doesn't know about client storage at all.
try
Session[xxx]=xxx;
or
Application[xxx]=xxx;
instead

Passing values between two "totally different" pages

To be clear, the two pages are only logically related in other words the values in my FirstPage.Aspx pass values to my SecondPage.Aspx so it control components and certain attributes of the controls in my SecondPage.Aspx, the SecondPage.Aspx is not a redirect or transfer from FirstPage.Asp. sorry am so sick of reading about all the answers but the one I actually need!
Consider the firstPage contains a textBox which get a value from the user or the web admin to set his preferences about the gridView page size on the SecondPage or a Text property of a label on the SecondPage
I want to explore my options to do so
PS: I was told to use a database to store values from the first page then on the page with my Label for example I connect to the database and retrieve the value and set it to the label...is this a best practice to let the page connect every time it loads to set some values sometimes it's just an int like 5, and most of the time I'd be connecting already to the database to display some table's data in a gridView or any databound control!
EDIT:
Sorry if I was a bit rude, it just hit me that I'm mainly getting the same answer that I read which is totally not my case!..and of course thanks to some of you mentioned the database solution, I hoped I could get an example or an article for my particular case since I think even it's simple but yet it's essential...
ASP.NET framework provides several mechanisms to maintain context that lasts across several HTTP requests. The data you want accessible across calls, can be stored in this context. All you have to do is decide how long do you want this context to be maintained (because it consumes resources), and if you want this context to be available across more than one server.
Application State : Which is maintained for the lifetime of the application i.e. from when the application is first loaded by ASP.NET, till it is unloaded for whatever reason.
Session State : ASP.NET is able to identify a series of HTTP requests emanating from a specific client (IP address), close to each other in time, as a session. It can create a session context that persists across such a session, in which you can store data that is accessible to the calls in the session. The session state can be made available across server boundaries by associating it with a DB or shared memory.
Database
Viewstate : You can use Viewstate to maintain context, but keep in mind that Viewstate is transferred over the wire for every request / response. It has been known to get quite large, specially if you use controls.
Cookies : Again, transferred on the wire for each request / response.
You can use:
Session variable
Cookie
Database value
each one of them have their own pros and cons
If you want the value to be stored the next time they come to page 2, use a database value. if not, use a session variable.
The database value will give you a persistent value, and you can then store other such user variables there.
the session will give persistent data, but only for the browsers current session. The data will be lost if their session times out.
From all you've stated, i would assume a database value.
U can use cookies, session etc but if you want to pass something that defines the whole content of the page, like an ID of some sort, you might just want to put it in the QueryString. (ex: default.aspx?id=4)
Cons: everyone can read (or change) the value, not usable for critical data
Pros: everyone can read the value, and the link can be sent to others
I'd suggest you start here: Get Started with ASP.NET
If I understand your question, you are looking to do Cross Page Posting. If one page isn't posting to a 2nd, you'll need to persist the data somehow (database, session, xml file, etc). But, from reading your question, you sound like you just want to cross page post...
Your question is very confusing, took me a lot of time before I could I understand what you actually need. Since there is no events in HTML, you will need to use JavaScript and some kind of web-service (AJAX).
Page A will store the value in database, and JavaScript on page B will constantly check database for new values, get them and output to the user. In order to that it needs to connect to some webservice/webmethod that will return the value from database to your page. A good example can be found here.
Alternatively you can refresh page every 5 seconds using
<meta HTTP-EQUIV="Refresh" content="5">
and check for the new database value on Page_Load server event.
I think the better answer is "Control State"
Reference : http://www.asp.net/general/videos/how-do-i-use-control-state-to-persist-information-for-a-custom-web-server-control
but I couldn't get this implemented on my case, two different pages
for example : the web user control is placed on News.aspx and the textbox which will have the value to be assigned to the control on News.aspx is placed in myAdmin.aspx page!
and to be honest, I didn't quite understand the code
So! do you think this is the best solution ? if yes do you think It can be used for my case (two different pages) ??

How to store user entered values across a website using C#?

I am currently working on a website that will have a high volume of traffic on it. The website has only 4-5 pages on it but I need to pass values selected on page 1 over to page 2 where more values are stored and so on until the user gets to page 5 where all values are passed to a third party system using XML.
Currently I use a dictionary object with roughly 20 keys stored in a single session object to hold the values across the different pages. I do this because some of the values are not just simple values like 'name' or 'age' values but can be complex like holding a dataset of results from an XML call on page 2.
I have read everywhere that global variables are bad so I am wondering if there is an alternative to using Sessions for this example? I cannot use a database to hold these values because of the way some of the values need to be stored (i.e. my variables are not just strings/ints). If I was to use global static variables how could I ensure the global variables are unique for each user?
Thanks for your thoughts.
Rich
** Edit 1 **
I am storing the current sessions in ASP.NET Session State and not inproc. I am just trying to figure out if what I am doing is bad practice or just generally accepted as an ok way of doing things. For example on the second page I get a XML result that I store as a dataset in my session for use on page 3/4 of my site. Should I be store/passing this info another way?
I cannot use a database to hold these
values because of the way some of the
values need to be stored (i.e. my
variables are not just strings/ints).
You actually can. You can serialise you object graph and store it as binary column in the database.
Additionally you can have this functionality out of the box and still using SessionState.
Here is an article on how to Store Session State in Sql Server.
So I would recommend to use Session but store the session state in the database.
Sessions are the right choice. The "global variables are bad" argument is a good one, but it's describing global variables, not session variables and pertains to how you organize data being passed among methods within your application. Storing data between pages can be done in only one of three ways:
Store the data in hidden fields or cookies (so everything gets passed back and forth for each page request). You could do this by just serializing your XML and other fancy data, but it sounds like a terrible idea.
Store the data in a database, flat file. This is a fine idea, but you'd still have to do the serializing work yourself.
Store the data in a session. This is exactly the same as option #2, except that C# is doing the serializing for you, and then saving the results in a flat file.
You do not have to do any work to separate the data of one user from another. Every visitor gets a unique session, and the data you store there won't ever be applied to another user (excluding a malicious attack such as a hijacked session).
I would think session is the appropriate place to put things that are relevant to your 'session'. It is true that over-using/abusing session can bite you with excessive memory consumption, but the alternatives can be a bit slower, just depending. Also, if you use SessionStateService or store the Session in SQL Server, you have slow-down in serializing/deserializing the session objects on each request.
You can use ViewState, but that means all of the data will get serialized to the HTTP Form, which means it will get passed back and forth on subsequent requests. Also, I think ViewState gets dropped from one ASP.NET form to the next, so unless you are on the same form, that won't work.
You can store the data in the database. One way is to have Session use SQL Server. If I were to use a database for this problem, I don't think I would use session in SQL Server though simply because if you store it yourself, then you could recover previously entered data.

Categories