In which situations should we use Query-Strings (VaryByParam) to achieve Caching in ASP.NET?
Can anyone give an example of a real-life situation in case of an web-application?
Products.aspx?productID=12345
Obviously you don't want the output cache of Products.aspx to have the data for the first product that got requested.
In detail
If I hit Products.aspx?productID=12345 the page will be processed for me, look up the info for product 12345, and cache the results. Then you hit Products.aspx?productID=54321, the page will not be processed for you but products.aspx will be retrieved from the output cache and you'll see the info for 12345. Not good. VaryByParam resolves this.
The most classic example may be: A product catalog
It may have a URL structure like so:
http://www.myshop.com/Catalog/ViewAllProducts.aspx
http://www.myshop.com/Catalog/ViewAllProducts.aspx?PageNum=123&PageSize=50
http://www.myshop.com/Catalog/ViewProduct.aspx?ProductID=12345
The first URL is the complete list of all products. There's no querystring here, but the second URL is the same page but with pagination. The Page Number (PageNum) and the number of items per page (PageSize) are both querystrings, so assuming the user couldn't re-order the product list, two different users requesting the:
http://www.myshop.com/Catalog/ViewAllProducts.aspx?PageNum=123&PageSize=50
URL would be getting the same information. The first request could cache this data so that the second request at a later time doesn't need to go back to the database to get the product items (and the details related to them: price, description etc.) in order to display them.
The third URL is a single product detail screen with the Product ID (which could be a unique identifier from the database) as it's single querystring parameter. Multiple requests for this will almost always need to return the same data (unless the price or description or some other element of that specific product changes on a frequent basis). Caching based upon the "ProductID" querystring (and it's variations in value for different products) will greatly reduce load of the database. Ensuring the cache duration isn't too long will ensure that the cache is expired in a reasonable time should the actual back-end database data change.
Related
How do things like google classroom do this:
classroom.google.com/c/(random characters here)
When you go to that link, because of the random characters, it knows what information to show
how would I do something like that in asp.net
Well, in .net you often might have grid or pick list of say hotels. When the user clicks on a hotel from that list, then you can jump/navigate to the hotel and display information. In these cases you actually want to AVOID having to use parameters in the URL. So, you can use session() to pass the value to the new web form/page.
However, often you might want to say email a link to someone else, or say send a email with a link called:
Click here for your Hotel Booking details.
So for above? What is often done is you create a table in the database. I often call it tblHotelJump or whatever. In that table you have this:
ID: (standard PK value all tables have).
CusotmerID: the PK of the customer - you might not need this, but if you using logons
and security - then you might only want the the link to work for the given
user.
HotelID: - PK value of hotel. This is where you can now pull the Hotel information
from the hotel table. (or maybe the booking table ID
JumpGUID: {3434sl%$#*} - a random generated number or GUID is often used.
userLogonID: internal user logon ID - obtained from logon authentication system.
So, now, we can pass a URL like this:
www.MyBookings.com/HotelInformation.aspx?JID={3434sl%$#*}
So the above is now a link you can send to a user.
They click on above, and your code behind on the page load does this:
If Not IsPostBack Then
' get parms
Dim strGuid As String
strGuid = Request.QueryString("JID")
So the above gets/grabs that parameter.
Now you code pulls that one row from the tblHotelsJump like this:
Dim cmdSQL As New SqlCommand("SELECT * from tblHotelJump
where JumpGUID = #GUID ORDER BY WhenTime DESC", GetCon())
cmdSQL.Parameters.Add("#GUID", SqlDbType.NVarChar).Value = strGuid
Dim rstGUID As DataTable = MyrstP(cmdSQL)
If rstGUID.Rows.Count > 0 Then
' Ok, valid jump row, get Hotel information and display it.
So now we can display hotel information since we have the HotelID and can display that data record.
Now in some cases, you might see something like:
www.MyBookings.com/ShowHotel.aspx?ID=343
And again the code will now simply use ID 343 and pull that hotel information from the database table with ID = 343. This idea ONLY works if you don't need security. So, say weather for a city. But you can't and don't want to use the actual database ID like above, since then users can type in ANY number and not just 343 in above example
In fact in the VERY early days of the internet, apparently a credit card company used a ID with customer number. if you typed in someone else customer number, then you could see their information!!! So using parameters is not appropriate for all cases. For public data, sure, it works well and makes sense. No harm done if you change the city parameter in the URL for weather.
So, that's why a GUID or some next to impossible number to guess is often used. Now for weather in a city? Well, then that don't matter and the WHOLE idea is to allow users to get/see the weather in any location. But for sensitive data? Then you need GUID.
And on top of the above, in that "jump table", I also included the User ID, and thus I would not display that web page unless:
The user is logged on (so a page protected by valid logons).
The Hotel information I pulled from that jump table ALSO matches the user logon id.
So, in a lot of cases? I think the parameters in the URL is VERY ugly and messy. However, for VERY large scale web sites they often use the parameters in the URL since then their server side code does NOT have to chew up memory and resources to hold/retain/keep the session() data. But with session() then you can jump around and use URL's without ugly parameters. So in .net we often avoid parameters, but in some cases the parameters in the URL is desired since then you can send/share that link. So for a say "click here" to view your order? Then sure, a GUID in the link may well be used. But even then, once that first page is hit with the GUID (along with above security), then any additional pages to view things about the order will not in fact require the parameters.
So paramters are easy, often used, and they reduce loads on the server side software, and as above shows, most development languages for the web have a "ready made" easy way to grab/get/use parameters in the URL. However, as noted, unless you building the next google, or say you need to send a customer a "link" to allow jumping to a particular order? Well then in .net we tend to avoid the parameters because we don't need them most of the time and .net has a whole bunch of really cool OTHER ways to store/keep values and pass them from one web form to the next web form without having to use parameters.
But if you using a limited web scripting language, then using parms in the URL is often your only practical choice.
Problem summary
I am trying to fetch all customers with POSTMAN using the latest woocommerce API (v3):
GET/customers
Yet only a small segment is returned. The number of customers returned is 28 (X-WP-Total) which is much less than the 150+ customers I have in the system.
Do you guys have any ideas on why only a subset of all customers are being returned instead of all? Does this have anything to do with how I configure woocommerce? Or am I just using the API incorrectly?
What i have tried
My goal is to create a small application to look up a customer by phone/email and then fetch the orders he had made.
Calling
GET/customers
Only returns a small subset of all customers and the rest is omitted.
Any customers omitted from the GET/customers will also return an empty array when i for example use
GET/customers?email=...
GET/customers?search=...
The requests returns an empty array on the omitted customers but
works on customers that was not omitted from:
GET/customers
Yet, given a known omitted customer ID, it is possible to look up that customer by sending a request to
GET/customer/{ID}
which does not make sense at all.
The solution is to set:
GET/customers?role=all
I figured that GET/customers only return by default customers whose role is 'customer'.
However, since I also make use of memberships/subscriptions, a customer would automatically get a new role assigned ('subscriber') whenever they opt-in for a membership. That customer would therefore not be included in the response since his role is no longer 'customer'.
Hope this helps anyone who stumbles upon the same problem.
Suppose that I have a table called persons and that a request to change any information about a person also updates that record's last_modified column. Would such a request still be considered idempotent? What I'm trying to find out is if auxiliary fields can be exempted from the criteria of idempotence.
If any information is changed on the database after a request (a POST request obviously, you would not alter a person record on a GET request) then it's not indempotent. By definition. Unless you only store stats (like logs).
Here it's not the last_modified column which is important, it's the change any information about a person.
A GET request is indempotent, you can take any uri and put it in an <IMG> in a web page, browsers will load it without asking, it must not alter anything in the database, or in the session (like destroying a session is not indempotent). An indempotent request can be prefetched, can run in any prioity (no need to care about the order of several indempotent queries,none of them can impact the other), etc.
I'm looking for some general advice. The site I'm currently working on is full of duplicate content that's about to be deduplicated. But it was built that way to track different audiences visiting the pages by reporting on the URL hits.
Current Links
www.MySite.com/homeowner/painting
www.MySite.com/professional/painting
www.MySite.com/designer/painting
My concern is that at the end of the day, the person managing the analytics wants to be able to look at their report and say "We had X number of professionals visit the site." Simply deduping will elimate that.
I'm thinking Google Analytics might have a way to pass audience/tags in via the URL like this:
Example Links with Tracking
www.MySite.com/painting?tag=homeowner
www.MySite.com/painting?tag=professional
www.MySite.com/painting?tag=designer
Is this possible with Google Analytics? Does anyone have an example website using this?
I've looked into Custom Dimensions and Metrics but they seem to be overkill https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets
Custom Dimensions are not overkill, it's a reasonable idea for you to use them (because segmentation is what they are for, really).
Using a url tag has a couple of disadvantages. For one The tagged pages will appear as three distinct rows in your reports - you will be unable to get an aggregated number for www.MySite.com/painting, instead you will have three Urls (or as many as you have parameters).
Secondly, homeowner etc. are attributes that belong to a session, or even a user (if the role cannot change from visit to visit). However if you track them via url parameters they have only a hit level scope, i.e. they are recorded as a property of the viewed page, not the viewing visitor. If you record this as a session scoped variabe you need to set it only at the first pageview, and the value will be applied to all subsequent pageviews for that session.
So an easy way (example assumes you are using php) might be to use
if(isset($_GET['tag']) {
ga('send', 'pageview', {
'dimension1': "<?php echo filter_input(INPUT_GET, 'tag', FILTER_SANITIZE_ENCODED); ?>"
});
} else {
ga('send', 'pageview');
}
in your tracking code after you have created a session scoped custom dimension in your property settings ("dimension1" referring to the first custom dimension in your account, the numeric index changes for each dimension. The dimension name is only used in the reports, not the tracking code). You need to be careful not to send an empty value when the query string is not present - a session scoped custom dimension only records the last value from a session, if you send empty values you overwrite the value you recorded at the first pageview.
Alternatively you can do this without changing the tracking code at all - create a custom advanced filter to capture the value from the query string, a second to copy the value to your custom dimension and a third to remove the query string from the url. However while that's a neat trick using code is much easier.
I have read this and many other links the past few days.
The problem is that I need to have a unique identifier for each tab or browser that a user has open for mysite.com (example site name)
I cannot use a unique session, as when I open mysite.com and have e.g. selected "carrots" in the session, then all the other tabs/browsers for mysite.com now has "carrots" in the specific session value.
But still the server obviously identifies each browser/tab uniquely. Is there a way to get hold of this unique browser/tab ID, or to create a unique one?
I am not referring to generating a unique ID oneself via JavaScript, I saw some good examples on StackOverflow. The problem would be that I'd need to implement it on each master page and carry it around between master/non master pages. Also for e.g. In my instance it won't work as I can have the browser open and it would generate 20 different IDs if I ran it 20 times across a few pages e.g. when I cannot transfer the value across ports.
So please, not to waste everyone's time, this is not a random GUID creation question, this question relates to obtaining a unique recreatable ID (if it gets lost)for each tab/browser, preferably identifying by the link to the server.
This is a big topic you've touched on.
If you only need to persist the ID during a form submit, you can take the approach of the client-side window.name property and use the window.onload to propagate a hidden field with that value.
But this won't work when user is following hyper-links (click on a link on a site).
onload: check if window.name is set; if not set, assign a GUID. if set, set a hidden field=window.name. So, on submit, your form will have the hidden field with the window.name GUID.
You can also use the HTML5 window.sessionStorage which will solve all your troubles, but that don't work on older browsers.
If you need support backward-browser AND non-submit type, then you will need to write some pretty complex cookie/session management on the client side. Not pretty. Just hope the above 2 is sufficient.