How can I get dynamic data shared between a custom action attribute and the action method?
My scenario, I am utilizing a custom action attribute to cache data in Redis. In this custom action attribute, I am logging metrics for how long it takes to get data from the cache vs getting it from continuing with the code. For some instances, I cannot utilize this custom action attribute and I'm calling cache methods like, _cache.TryGetAsync(key); inside the action method. TryGetAsync is an extension method I wrote that just wraps the GetAsync(key) call in a try/catch so that if the call to Redis fails, it will continue with getting the data from continuing with the code.
I would still like to try and log metrics when the code is making direct calls to cache via the try extension methods that I wrote.
I was thinking about creating a CacheLogging attribute that I could place on the action method. Then, in the BeforeActionExecutionAsync, I could start the timer and in AfterActionExecutionAsync, stop it and log. But, I need the try extension methods to set the context of where the data is retrieved.
For example, TryGetAsync would set the context to FromCache. Then, TryAddAsync would set it to FromServer. If TryAddAsync is called, that means that the data was not found in the cache and continued to get it from the code and populated the cache with this new data.
The problem is, I can't figure out how to reliably set this context in the method so that the attribute can read it in the AfterActionExecutionAsync. I thought about DIing a Singleton ICacheContext that the CacheLogging attribute would have access to and could be passed as an optional parameter into the try extension methods. But, with the possibility of the action method being called simultaneously multiple times, the Singleton would need some sort of Dictionary with a unique id per call that both the CacheLogging attribute and the try cache attribute would somehow know that way they knew which call the context was for. But, parameters need to be static/const/etc to be sent to the CacheLogging attribute.
You don't store performance in attributes.
If you need to store performance, define global variables that track performance for different methods and commit the data to your datastore every x, or write it to a (text) log.
You should try an AOP approach using Castle Windsor interceptors. See: https://www.tabsoverspaces.com/233716-simple-caching-interceptor-aspect-for-castle-windsor
Related
I am new to Razor Pages and looking for the best way to solve my problem.
Say I have an IndexModel class, that has some properties that rely on a DB context that is injected via the Constructer, such as a drop down list of Membership Levels, that comes directly from a table...
My question is what is the best way to handle populating this drop down list that I have for ALL requests that results in the same page being reloaded / returned. I know that I can put logic in OnGet to set up the list, the problem arises if say in OnPost, ModelState.IsValid is false, and so the page is returned with Page(). If I don't explicitly reinitialize the select list in OnPost, then I get a null reference exception, which is fair enough. Rewriting the code in the OnPost method goes against DRY principles, so I looked to writing a ConfirgureProperties() method in the class when needed.
Then by testing, I found that I can just set up a constructer that will take care of populating properties for me whenever they are needed, and I don't have to call anything else. Even when DI is involved, the injection is resolved at the top of the constructer, then I can use the context to do what I need for the other properties later in the constructer. I have seen no examples of this anywhere online, I only ever see people using constructers in page models that handle DI EXCLUSIVELY.
Is there a reason I SHOULD NOT be doing this, like bad coding practice or something, or is it ok for me to use page model constructers in this way?
Thanks
You only need to make the database call to repopulate the options in OnPost if ModelState is invalid. Chances are, if you have set up your validation correctly, that 99% of the time validation errors will be caught on the client and you won't need to repopulate the options.
Obtaining data from a database is costly, and you should only do it when necessary. So using the constructor approach contravenes this principal.
It's not like you are saving a lot of code either. Your ConfigureProperties method will only be called in two places in the PageModel.
I'm new to FluentValidation and am trying to create a validator that accepts some context/parameters at validate time. I've created a custom validator and in the constructor I have something like:
RuleFor(request => request.someField).Custom((request, context) => {
var foo = context.ParentContext.RootContextData["someDependency"];
});
And in the calling code I do:
var validator = new FooValidator();
var context = new ValidationContext<SomeRequest>(request);
context.RootContextData["someDependency"] = someDependency;
validator.Validate(context);
which causes:
System.Collections.Generic.KeyNotFoundException: The given key 'someDependency' was not present in the dictionary.
Any ideas? The reason I want to pass in some context parameters is that they come from the database. If I instead pass that into the validator constructor, then by the time the validate method is called, those context parameters might be out of date. I also don't want to do the fetching from the database in the validator constructor as I will also need to fetch the same data before/after the validate method is called, and database caching is not possible in this scenario, so I'd like to avoid the unnecessary database roundtrips. I've read and am doing what seems to be the same as what is described https://docs.fluentvalidation.net/en/latest/advanced.html#root-context-data
As mentioned in my OP comment, the code looks sound but it's likely failing at the MVC validation pipeline stage and never makes it to your Validate invocation. With the former as it stands you've not added your dependency to the dictionary so it barfs.
There's probably a couple of ways to solve it. My first thought would be to introduce a rule set so this rule only executes server-side as part of your Validate invocation. There's a whole section on rule sets in the doco which covers it pretty well. You may need to combine it with a CustomizeValidator attribute so that the rule set doesn't get executed in the MVC validation pipeline (I've never had to when using a server-side rule set but I've mentioned it for completeness).
The nice thing with this is that you probably won't need to change much of your existing code; you've mentioned you load a number of dependencies into the validation context so it could be a good fit.
Another methodology that looks good, but one that I haven't tried myself, would be to populate the validation context in the BeforeMvcValidation validation interceptor. The value of this option is going to depend on how you gather those dependencies and whether they are used for anything other than validation. It'd probably require more effort than a rule set based on your implementation description as well.
i have tried to surf the internet but i could not get anything related to what i want.
This is in relation to ASP.Net. But could be any other instance as well.
Following is my attribute
class SomeAttribute :Attribute
{
string someparam;
string SomeParam
{
get{ return someparam;}
set { someparam = val;}
//the value generated for someparam is dynamically generated with respect to some attribute present in the request header.
}
}
it's similar to the [Authorize] attribute that .net uses in its asp .net memberships to validate if the user has logged in and it redirects him back to log in page if validation fails.
I have an attribute associated with a method like below:
[SomeAttribute]
public void someFunction
{
//i want to retrieve here the value of someparam jus generated before entering this method.
}
Note that i don't pass any value or used any named properties in this attribute. It is simply going to check a condition for me whenever the method is called and return true or false and accordingly the function is either called or not.
In my case, After validating, it generates a value and that value has to be shared with the function to which it is associated 'somefunction'.
i know reflections can help me get the attributes associated with a function and the value of its properties.
But here i dont want to fetch the value from some other function. And i dont want to just fetch the attribute either.
As i mentioned earlier when the function is called the attribute will work upon that. What the attribute does is fetches some data from request header and does some processing and generates a value. Now this value has to be passed on to the function just after that.
Well, what you want to accomplish is certainly possible, but it would not be an optimal use of the run-time or the MVC model.
In this particular case, think of an attribute as an annotation. It's something you use to mark a function, controller, etc. so that its execution behaves differently at run-time. The attribute itself should not be doing the bulk of the work, rather just signalling to other pieces in your design to behave differently.
It seems like you want to check some header values, and calculate something based off of that. You can use extension methods off of a Request class to accomplish this.
Now, let's say that inside your Controller's function, you want to guarantee that the header values exist. You can have an attribute called RequireHeaderValues that implements IActionFilter. The attribute would check the header for the required values and if they don't exist, it routes the response to another location or somehow indicates error. This way, when inside your function, you call the extension method off the Request object, you are guaranteed that the values will exist. The MVC run-time will automatically call your filter attribute for you. For more info, see this.
I have a controller with several action methods requiring the same list of data from a certain database. Since most of the actions were going to need access to the list, I quickly populated a private member variable with necessary list of data items directly in the constructor of my controller.
All was well and good until the database went down and an exception was thrown in the constructor. Apparently, that circumvents the normal HandleError functionality.
My goal is for this exception to be caught and the user redirected to an error view.
What is the proper way to load the data for all actions?
Is it appropriate to put a database call in OnActionExecuting?
Is there some way to do decorate the specific actions with an attribute that loads the data?
Am I over-thinking it? (After all, I could just drop a private method in the controller and call it from each action requiring the data)
You could create the private method and have it populate your list (if it's not already populated) and then return the list. This way your only calling the method to populate it when it's needed the first time, and you take fragile code out of your controller's constructor. It's going to much easier to handle the exception in your action methods than elsewhere.
Controllers (as objects) are being instantiated for every request. Therefore, there is no need to optimize data within controller which would be "reused" in many actions (as Jeff Reddy suggested). Unless you call an action method explicitly from another action method (which is bad practice anyway).
Make a private method GetData() that gets data from database and call it in every action.
However, you probably do want to avoid expensive database round-trips that get the same data over and over, then consider using HttpRuntime.Cache. You could save data there on the first call to GetData() and retrieve it from cache on subsequent requests.
If you need the model inside all your controller actions you could define a custom model binder for a given model and overriding the BidModel method which will query the database and populate this model. Then your controller actions could take this model as action argument:
public ActionResult Foo(MyModel model)
{
...
}
public ActionResult Bar(MyModel model)
{
...
}
If you don't need the model inside each action but inside each view you could externalize it as a widget using the Html.RenderAction helper.
I have a question concerning Monotouch.
The situation: I have 2 ViewControllers. The first (let's call it VC-A) looks similar to the contacts edit screen, meaning it has a TableView with multiple Sections each containing Buttons and TextFields. Now when the user clicks one of these Buttons, he will get to the second ViewController (VC-B), which displays a TableView containing data from the database. When the user clicks on any of these rows, VC-B will be closed and i want to display the selected database entry (string) as the title of the Button (in VC-A) which opened VC-B in the first place.
When I did an objective-C project last year, I managed to send data back down the stack by using delegates, but I haven't found a way yet how this works in Monotouch.
I have read several questions here on SO about using the AppDelegate or using singletons, but I'm not sure that this is the right way of returning data from a subview.
You can kind of copy the delegate pattern. Add a C# delegate to your VC-B that takes one parameter, some data structure.
In VC-B's "ViewWillDisappear", call the delegate it it is not null and pass the data on to it.
This way, your calling VC can get acces to the data but you don't need tight coupling between the two controllers. All it has to do, is register a delegate-method in VC-B.
As MonoTouch is .NET4 you can use Func<MyDataStructure> or Action<MyDataStructure> and don't need to use full qualified delegate types.
I have a static singleton class that I use to store "state" type data about my app - current settings and selections that are needed in many different places in the app. That's one way to approach this.
You could also pass VC-B a reference to VC-A when you create VC-B, so that it can explicitly access it's parent view and pass back values that way.
I actually prefer to use TinyMessenger for cross container calls I find this to be very very useful when you don't want to keep references to your heavy viewcontrollers around which could potentially result in memory leaks!
var messageHub = new TinyMessengerHub();
// Publishing a message is as simple as calling the "Publish" method.
messageHub.Publish(new MyMessage());
// We can also publish asyncronously if necessary
messageHub.PublishAsync(new MyMessage());
// And we can get a callback when publishing is completed
messageHub.PublishAsync(new MyMessage(), MyCallback);
// MyCallback is executed on completion
https://github.com/grumpydev/TinyMessenger