Asp.net core response caching by country - caching

I need to use use response caching for certain controller actions based on the country the request is coming from.
I have figured out how to get the country code from the request (it involves reading from a database, expensive, so I want to do this just for the actions that require a country), but I am not sure how to do the caching part.
I am thinking of writing a middleware (e.g., named CountryResolver)that will run before the response caching middleware and set the country SOMEHOW in the request and have the Response Cache middleware vary by country.
app.UseCountryResolver();
app.UseResponseCaching();
There are two main problems I am facing:
Problem 1-
I need that middleware not to run for every request, but only for some requests that are routed to country-specific actions. I am thinking of annotating such country-specific actions via a custom attribute (e.g., [CountryRequired]).
[CountryRequired]
[ResponseCache(VaryByQueryKeys = new string[] { "country"}]
public IActionResult MyAction()
{
However I don't know how the middleware can pickup the actions that have such annotation so it can decide whether to lookup the country or not.
Problem 2- "...set the country SOMEHOW in the request"
I was thinking of using VaryByQueryKeys and have the middleware set the country to a query string key named "country" BUT HttpContext.Request.Query collection is readonly. So I am not sure what other mechanism can I use for this.
Any help is very appreciated.

Related

how to implement Single Responsibility in laravel

I am so confused about how to implement and how to follow SRP (single responsibility principle ) in a Laravel controller.
Suppose we have a controller which we have to do these things:
e.g
public function StorePost() {
// check user login()
//check number of current user Post count =>which must be less than 10
//store post
//send an email to user which your post has saved
//return =>api:json /web : redirect
}
I know that I can implement some DB queries in the repository but I don't know how to implement others of my logic code to achieve SRP
Also, I know there is a Heyman package to achieve these but I want to implement it by myself.
SRP in this context basically means each class and method should only be responsible for a single behaviour/feature. A rule of thumb is a class or method should change for one reason only, if it changes for multiple reasons, it needs to be broken down into smaller parts.
Your storePost method should not bother with checking the user login, that should be handled elsewhere before invoking storePost. storePost shouldnt change if the auth mechanism changes like switching from api token to json web token or something else. Laravel does this in the middleware level with the auth middleware.
Checking the users post count, this can be checked in the validation stage. storePost shouldn't change if we add more validation logic. In Laravel you can use FormValidation for this
For storing the post, the controller doesn't need to know how to call the DB, you can use the active record style using the model class or maybe create a service or repository class if your use case requires that. storePost shouldn't change if we decide to change DB vendor like going NoSQL.
For sending email, again the controller doesnt need to know how to send the email like what the subject/body recipients are. storePost shouldnt change if we need to change the email layout. Laravel has Notification for that
For serialising the response to json, the controller doesnt need to know how to format the response. if we decide to update how our json looks, storePost shouldnt change. Laravel has API Resources for that
So, ultimately in this example, the responsibility of the controller method is basically to glue all these together. It basically does what you wrote down, it only responsible for maintaining the step by step behavior, everything else is delegated to someone else. if the behavior change, like adding new behavior e.g notify all follower, storePost will change.

Adding attribute to a user when register in Laravel 5.1

When a user Register, I want to add location data for the user.
I get those with GeoIP.
So, each time a user is created, I would like somewhere to add Country, City, etc.
I was thinking about setting Hidden fields in view, but I think it a hugly way to do it, and I'm sure there is a better way to do...
Any Idea???
Any time I create a record that needs extra data, involves inserting additional records into additional tables, etc, I create a service class. Something like "UserCreator" then I pass it the input, do any additional operations, wrap multiple database calls in a transaction and so on.
That said there are so many ways to do what you want. You could Input::merge(...) then save, you could separate the process of creating a user from your controller / route function, etc.
If you are just getting started with Laravel and/or your project is rather simple, then you probably want to look at Input::merge
I solved it using Request Contructor as said here in laracast
In the Form Request's constructor I inject \Illuminate\Http\Request. I can then add my value to the request instance as such:
public function __construct(\Illuminate\Http\Request $request)
{
$request->request->add(['date_of_birth' => implode('-', $request->only('year', 'month', 'day'))]);
}

Spring MVC - Keeping object state between ajax requests

Spring MVC 4.1
Hi,
I have a situation where, on a single page, there are several input fields. As the users enters numbers into these fields, a bunch of calculations will occur and update various other fields on the page.
I want this whole calculation model to take place in Java on the server-side. I really want to avoid replicating this logic in Javascript on the client.
What I envision is...
User opens the page, the object that does the calculations (let's call it Calculator) is created and its initial state is set (many of its fields are pre-populated with values).
This Calculator instance is stored and available for the duration of the user's time on that page.
Whenever the user changes a value in an input field, that new value is sent to the server via ajax and plugged into our Calculator object. The Calculator, re-calculates the other fields based on the new state and returns the results to the page.
The other fields on the page are updated accordingly.
The key here is that I'm not sending the state of all fields with each ajax request. I'm only sending the current value that was updated. Essentially, I'm trying to ensure that the form state and the Calculator state on the back-end are always synchronized.
I have looked into #SessionAttributes and #ModelAttribute.
The problem with #ModelAttribute, as I understand it, is that it will be re-created with each ajax request.
The problem with #SessionAttributes is that it is a session variable. What if the user has two of these windows open? And how do I ensure the object is removed from the session when they leave the page? etc...
Maybe there's no magic Spring bullet and I just have to figure out the session variable thing. But any pointers on dealing with this would be much appreciated.
Thanks!
You have a couple of options:
.1. Like you have said using the #SessionAttributes, however yes it suffers from the issue that you have mentioned, multiple instances of the same session will see the same variable.
.2. Store state somewhere else and re-hydrate the state using #ModelAttribute annotated method. I would personally prefer this approach, essentially when you create the form, create it with a identifier for the current state:
#RequestMapping(params = "form")
public String createForm(Model uiModel) {
uiModel.addAttribute("calculationId", UUID.randomUUID().toString());
return "calculationpage/create";
}
Then for subsequent ajax requests, ensure your previous calculationId is sent across:
#ModelAttribute("calculationState")
public CalculationState rehydrateState(String calculationId) {
//retrieve current state of calculation from some persistent store..
}
#RequestMapping("/calculate")
public String handleCalculation(#ModelAttribute("calculationState") CalculationState c) {
//you will get a calculationstate with the delta's at this point..
}
.3. Another potential approach may be to use session but disambiguate different instances within the session with a custom id:
public String handleCalculation(HttpSession session, #RequestParam("calcId") String calcId) {
CalculationState calcState = (CalculationState) session.getAttribute("calculation" + calcId);
}
You need any sort of persistent store outside session to store and retrieve the state of your calculator model. Like Biju said, I will go for solutions like No 2.

Hiding Query String Parameters

I have a GET action for creating records. Because the page is somewhat dynamic, I don't use a model to hold the data. I go off to do some OAuth, only to return to the create screen later on. In order to pass the data back, I am redirecting with a query string. I parse the query string in the GET action, and then show the view. The thing is, the query string is showing up in the browser. This displays pseudo-sensitive data.
Since I am only using the query string for transferring data, I am wondering if I can throw the query string away to prevent it from showing up on the browser.
Otherwise, is there a way to go to another action without redirecting? I've found, if I call the "other" action method directly, it tries to find the view of the original action. I can explicitly change the return View(viewModel) line to return View("create", viewModel) but that seems really dirty.
You should consider changing the action to accept POST requests. At least this will prevent the sensitive information from appearing in the browser. For extra security, your site should be served via SSL.
The other thing you can try is encrypting the sensitive values or the entire query string. The only problem is that this, too, will be preserved in the browser's history unless you require users to log in.
It looks like your action method is trying to do too much. Authentication/authorization is a separate concern which should not be part of the action method. It is better to move the authentication work in to an action filter.
Create an class that extends authorization attribute and override its OnAuthorization method to do your authorization work.
This frees your controller action method to accept POST requests.

RESTful URLs: "Impractical" Requests, and Requiring One of Two Request Parameters

I have a RESTful URL that requires either the offset or the prefix request parameter (but not both).
GET /users?offset=0&count=20
GET /users?prefix=J&count=20
What's the best way to enforce this rule? Spring has the #RequestParam annotation with the 'required' property for optional parameters, but I want to enforce an "either-or" rule on these two parameters. I know I could do it in the code, but is there another way to do it?
Also, what's the proper way to handle "impractical" requests? Say I have 100 million users; the following request, although properly RESTful, is not something I want to support:
GET /users <-- Gets all 100 million users, crashes server and browser!
What should I send back?
You can create two methods and choose one of them with #RequestMapping's params attribute:
#RequestMapping(..., params = {"prefix", "!offset"})
public String usersWithPrefix(#RequestParam("prefix") ...) { ... }
#RequestMapping(..., params = {"offset", "!prefix"})
public String usersWithOffset(#RequestParam("offset") ...) { ... }
what's the proper way to handle "impractical" requests?
The lesser-practiced principles of REST include the requirement that resources be "discoverable". If you are asked for a complete list of 800 million users and you don't want to provide it, you might instead consider serving a page that describes in some way how to filter the collection: for example, an XForms document or HTML containing a FORM element with fields for offset/prefix/count, or a URI template with the appropriate parameters
Or you could just send a "413 Entity too large" error - edit: no you can't. Sorry, I misread the description of whath this code is for
If you decide to go down the route of just sending the first page, I think I would send it as an HTTP redirect to /users?offset=0&count=20 so that the client has a better idea they've not got the full collection (and if your response contains a link to access subsequent pages, even better)

Resources