Passing Complex Object correctly without using TempData / ViewBag / ViewData - c#

For a website, consider this scenario:
Users input data, including a ID, and submit
A related controller will handle the request. At this point, one complex object will be created (by calling web services, with the ID) for a series of operations. e.g validation, etc
Return user a specific View
User input another set of data and submit
Another controller will handle this request. It requires the complex object used in step 2.
and so on...
Currently, in step 5, I will use the ID to call the web service again for getting the required complex object.
Is there any correct/efficient way, without using TempData/ViewBag/ViewData, so that I can reuse the complex object, once it is created, in step 2?
Edit:
Session is not allowed as well.

Normally, for web application, there're multiple options to store complex object depending on your need. I don't think there is a BEST way of doing, only the most suitable way and every solutions will come with PROS and CONS
SERVER SIDE
Session (I know you said cannot use session, but I just want to include it anyway): first option comes to mind, suitable for most web application. Since the modern web development are more on STATELESS, a lot of people want to avoid using Session at all cost. However, there're some specific infrastructure configuration to support session in STATELESS application such as distributed session or sticky session or you can save the session in a dedicated server or database.
PROS: easy to use, support web application naturally
CONS: need to configure a lot of things to work with STATELESS application
ANOTHER Dedicated server (Before anyone ask, I put it in the SERVER SIDE section even though it's another SERVER, but to me, whatever in our control is SERVER SIDE): a few options for you to choose here, first option could be to set up a cache server (Redis?) and retrieve/save using key (similar to session), or you can simply write an application to retrieve/save using your own logic.
PROS: reusability, extendability, works with all applications not just web, have its own scope
CONS: difficult to setup
Database: not a obvious choice, but database do support this kind of requirement
PROS: reusability, extendability, works with all applications not just web
CONS: performance issue
Other in-memory options (TempData, ViewBag, etc):
PROS: easy to use, well-supported with ASP.NET MVC
CONS: somtimes it's hard to pass around multiple views
CLIENT SIDE
There are so many options here to choose like use hidden fields, cookie, localStorage, sessionStorage, etc or even a simple query string will work
PROS: speed (since you don't need client-server transportation)
CONS: security (you cannot trust anything from client-side), not doing well with too complex object (heavy object), security (sensitive data), etc
SUGGESTED SOLUTION
I hope I understand your issue correctly but in my opinion, you should not store complex object, simply store the ID of the complex object in place of your choice, and make a query every time you need the object. So that your object is always up-to-date and you don't waste resource to store the complex object.
Hope it helps you.

If you want to project an object to a certain view, then forget about any storage (TempData/ViewBag/ViewData/Session) and then post the same object to another controller, the best way you can re-construct your object is to store the object's properties as hidden <input> controls.

Related

What is the best way to store some immutable and highly accessed data in C#?

Some background - I am working in a project which requires a kind of headshake authentication. The external service will send a request with a Token, and I will answer with Validator. Then it will send a second request containing the same Token and the data I should store in my database. The token is also used to get a couple extra fields that are required to insert the data in the database. Due to several project constraints and requirements, this "api" is implemented in Serverless (Azure Functions).
Since there are only 100 and something token-validator pairs that are not often updated (I will update manually every month or so), I have decided about not querying the database every time I get an incoming request. Normally I would simply use caching in C#, but since I am working with Functions, the code will be executed in multiple changing processes, which means no shared cache. I also think that using a cache service, such as Redis or Azure Cache would be an overkill.
My current solution - Currently, I am storing the data in a Hashtable that maps a Token to a ValidatorModel object that contains the validator and the extra fields I require. It works pretty well, but since it is a big C# object, it is a pain to update, the IDE lags when I open it, etc. I also don't know if it is a good idea to have it hardcoded in C# like that.
What I have been thinking about - I was thinking about storing a binary protobuf file that contained my Hashmap object. I am unsure if this would work or perform well.
My question - What is the best way do store such data and access it in a performatic way?

Filtering with Web API

I have an application with several Web API controllers and I now I have a requirement which is to be able to filter GET results by the object properties. I've been looking at using OData but I'm not sure if it's a good fit for a couple reasons:
The Web API controller does not have direct access to the DataContext, instead it gets data from our database through our "domain" layer so it has no visibility into our Entity Framework models.
Tying into the first item, the Web API deals with lightweight DTO model objects which are produced in the domain layer. This is effectively what hides the EF models. The issue here is I want these queries to be executed in our database but by the time the Web API method gets a collection from the domain layer all of the objects in the collection have been mapped to these DTO objects, so I don't see how the OData filter could possibly do it's job when the objects are once-removed from EF in this way.
This item may be the most important one: We don't really want to allow arbitrary querying against our Web API/Database. We just sort of want to leverage this OData library to avoid writing our own filters, and filter parsers/builders for every type of object that could be returned by one of our Web API endpoints.
Am I on the wrong track based on #3? If not, would we be able to use this OData library without significant refactoring to how our Web API and our EF interact?
I haven't had experience with OData, but from what I can see it's designed to be fed a Context and manages the interaction and returning of those models. I am definitely not a fan of returning Entities in any form to a client.
It's an ugly situation to be in, but when faced with this, my first course of action is to push back to the clients to justify their searching needs. The default request is almost always "Well, it would be nice to be able to search against everything." My answer to that is that I don't want to know what you want, I want to know what you need because I don't want to give you a loaded gun to shoot your own foot off with and then have you blame me because the system came grinding to a halt. Searching is a huge performance killer if it's too open-ended. It's hard to test for accuracy/relevance, and efficiently index for 100% of possible search cases when users only need 25% of those scenarios. If the client cannot tell you what searching they will need, and just want everything because they might need it, then they don't need it yet.
Personally I stick to specific search DTOs and translate those into the linq expressions.
If I was faced with a hard requirement to implement something like that, I would:
Try to push for these searches/reports to be done off a reporting replica that is synchronized with the live database. (To minimize the bleeding when some idiot managers fire up some wacky non-indexed search criteria so that it doesn't tie up the production DB where people are trying to do work.)
Create a new bounded DbContext specific for searching with separate entity definitions that only expose the minimum # of properties to represent search criteria and IDs.
Hook this bounded context into the API and OData. It will return "search results". When a user selects a search result, use the ID(s) against the API to load the applicable domain, or initiate an action, etc.
no. 1. is optional, a nice to have provided they can live with searches not "seeing" updated criteria until replicated. (I.e. a few seconds to minutes depending on replication strategy/size) Normally these searches are used for reporting-type queries so I'd push to keep these separate from the normal day-to-day searching options that users use. (I.e. an advanced search option or the like.)

How to properly share an object in my controller between methods with ASP .NET MVC?

I'm working with ASP.NET and I want to load once a big object (specific by user) in my controller and then use it in my view.
I though about a static property but I find some problems with it.
See : Is it a bad idea to use a large static variable?
I'm not familiar with this language and I have no idea how to properly share the same object between the different methods for each user. Could you tell me how to do that ? Do you know if singleton could be a solution ?
A singleton won't help you here if this big object is going to be different for every user.
Without knowing all the details, I'd say perhaps your best option is to store it in the Session object,
HttpContext.Current.Session["bigObject"] = bigObject;
Depending on the size & traffic, this can have performance problems, so I'd suggest you read up on the pros and cons of using Session
If you want to get to use something for the next simultaneous request, then use TempData - which is a bucket where you can hold data that is only needed for the following request. That is, anything you put into TempData is discarded after the next request completes.
If you want to persist the information specific to user, then go for Session. With session, you will have timeout, so that after certain amount of time the data stored in session will be lost. You can configure this value to much more bigger value. Apart from that when you go for Webfarm of servers, then maintaining session will be a problem, probably you might need to go for managing session in SQL Server or in some other store.
Alternatively you can Use Runtime Cache object in ASP.Net MVC to keep all the common data. Cached data can be accessed fast and we have other benefits like expiring cache etc. You can share this Cache object across users, or you can maintain different cache objects for different users, that is purely dependent on your logic. In case of webfarms, yo u have distributed cache servers like redis, Azure Cache service etc., which you can use them.

Persist List of Objects Between Pages - ASP MVC

C# - ASP MVC - .NET 4.5 - Bootstrap - Razor
I have a form wizard (http://vadimg.com/twitter-bootstrap-wizard-example/examples/basic.html) that is used to setup a complex object (obj1). A property of obj1 is a List<obj2>. On one step of the wizard I want to add multiple obj2's to the list. Since obj2 is slightly complex as well, I thought I would use another wizard to help build it. Except I need to persist this List<obj2> on wizard 1, while I'm off in wizard 2 building another obj2.
My first thought was to use a session to hold the List<obj2>, I was just wondering if that's a good option, or if there would be a better one? The user may leave from Wizard1 to go to Wizard2 and come back multiple times.
There's no perfect answer here; each approach has trade-offs. But here are some options that I can think of (and these are independent of ASP.NET/C#)
Session (as you suggest)
This will store data in web server memory (by default). If you have a lot of users, this could be a problem.
You risk the information being lost when the user gets a new cookie/the session times out.
Potentially better performance that a db, depending again on the number of users
Database (as you mentioned)
Could cause more database traffic.
Can save information for user even if they close a browser, switch computer, the power goes out, etc.
Maybe a separate NoSQL database just for transient wizard data would be worth trying.
Cookie (store data on the user's computer)
Users can potentially tamper with/view the data
There is a limit on cookie size (4 KB each?)
Local storage (HTML5)
Similar to cookies
But not such a small limit
Not every browser supports it (may need polyfill)
Form/Post/Hidden/ViewState
You could just post the data and drag the information from response to response
But this gets really annoying with back buttons & timeouts
Lots of work, and again, the user can tamper with the information

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

Categories