I have created a few razorpages and have been putting a lot of code inside the Post and Get methods i.e
public async Task<IActionResult> OnPostSaveSetStatusAsync(int? id) {
}
think of it as opening a detailed page containing a button that should set a status on a specific order.
I now need to set the same status, i.e executing the same code but from a view (another razorpage) having the order selected.
if I put all my code in helper classes there is a lot of methods parameters that need to be sent in. i.e sqlcontexts, cache, httcontext etc. is this a good approach anyway?
...or should I just create methods in the original razorpage and call it from all other places? (like helper methods inside the class)
thanks
Plain and simple: if there's any code that needs to be shared in multiple places, it should go into another class that can be used as a dependency where it's needed. The listed dependencies don't seem like too much, though you should strongly consider whether you need a dependency on HttpContext. Most of the time, you should really just be passing in some value to a method. For example, if you need to work with a user id, pass the user id into a method on your helper class, rather than making the helper class take a dependency on HttpContext and fetch the id itself.
If you still have too many dependencies, then you're likely breaking the single responsibility principle. You may need multiple helper classes, or a different strategy entirely. It's hard to say anything definitive without knowing exactly what you're doing.
Related
I wanted to make my Controller methods register as [HttpGet] if they have "get" in the method name, the same goes for [HttpPost] if they have "create" etc.
How can I create an "attributeAssigner", that would go over the assembly and do the job?
In fact you can't. The example Ygalbel mentioned is a solution which, to my opinion is kind of cheat.
The code in the example creates another class (a proxy) which inherits from the class you want to apply the attribute(s) to. In fact, if you use reflection to retrieve the custom attributes decorating your class (its properties and methods) you'll find none of them. The instance of a class in the suggested solution is instance of another class, not yours!
I'm not 100% sure, but I can guess ASP.NET (Core) does exactly this, so it'll find no attributes decorating your controller's actions.
In order to use the suggested solution you'll need to write some code which will have to do the following:
Inspect your controller class and figure out where to add the attributes as you want,
Use the solution described in the example,
Unregister the original controller a part,
Register the proxy created by the example code as substitute to the original with the provider.
Maybe this text could be a good starting point but still, your idea needs to be clarified.
Anyway, if you do insist on its implementation I wish you good luck. This is part of the advanced topics in ASP.NET Core.
HTH
So for example I have this Web Api controller class AdministratorController and it contains a lot of tasks:
Create
Delete
Edit Password
Update
Get
Get all
Etc...
Now I have all these Tasks in 1 file AdministratorController.cs. But with all comments and annotations the file is pretty long.
Is it a good method to split this controller up into partial class pieces to make developers that search for a specific function get quicker to their destination? Or is this abusing the partial keyword
So for example I have a folder structure of:
--Controllers
⠀|-- Administrators
⠀⠀⠀⠀|-----AdministratorCreateController.cs
⠀⠀⠀⠀|-----AdministratorDeleteController.cs
⠀⠀⠀⠀|-----AdministratorEditPasswordController.cs
Obviously, this is a opinionated answer. Technically speaking, yes you can. It will compile.
I think you are right to split this into multiple files if it gets to long.
You could have partial classes. Or you could just have multiple classes. No one forces you to put all those methods into a single controller.
Personally, I'd opt for the multiple classes for practical reasons. You probably do dependency injection and you probably do it via constructor injection, because this is the default. With partial classes, which just means one big class but multiple files, you now need to edit your current file, plus the file that the constructor resides in to add a new service. It also means all the methods will need the DeleteDataService injected, although only the Delete method uses it. If you had one controller per method, you'd have the constructor in the same file and the other classes are not dependent on it.
But if for example you do injection via [FromService] attribute in your method then there is little difference between your two choices.
Structuring them in different files if keeping them in one file is too long is good. So good, that I don't think it would be too bad, even if you picked the "wrong" method to do it. So pick the one that seems most practical to you.
It depends on what you mean by "readable." To the extent that we must read a class, whatever we have to read doesn't become less by being placed in separate files. There's just as much to read either way. It could even be a nuisance looking through parts of a class across separate files looking for a particular member.
Partial classes might make us feel like we're separating code when we're really just making bigger classes. If we think we're making anything simpler with partial classes then they could even make our code harder to understand by encouraging us to add more to a single class while separating it into different files.
I'm not railing against partial classes. This stuff only exists if there is a use for it, and I don't mean to imply that anyone who uses them is abusing them. One example is autogenerated classes, like when we add a service reference (do we still do that?) We might make some modifications to the class, but then they get lost if we update the service reference and redo the auto-generation. If we put our custom code in a partial class then we can generate part while leaving the rest intact.
I'm building a web app using ASP.NET MVC 4, with data storage provided by T-SQL database via Entity Framework. I'm integrating audit logging as I go, and I'd like to provide a nice human-readable summary of the action, so that I can present a friendly logs view with clear statements like "User Bob logged in", "User Alice updated article 'Foo'", etc.
An audit record currently consists of:
GUID
timestamp
user ID
action category (controller name)
action (action method name)
IsError (boolean; true means either this is a record of an error, or this action did not complete successfully)
blob of serialised details
At the moment, my logging uses a custom attribute which implements IActionFIlter; the OnActionExecuting() method logs the attempted action (serialising things like URL, parameters etc to the detail blob) and the OnActionExecuted() method goes back and sets IsError to true if there are no errors, and appends either the returned result or exception with error message and stack trace etc to the details. I want to add another column for description strings, but I can't see a tidy way to do it.
The furthest I got was to pass a string to the attribute, something like "User $user logged in" and then have the log method scan the string for the $ character and replace that word with anything from the parameters dictionary whose key value matches that word (minus the $ character). This is a little limited; for example, if articles are stored by ID number, then the best you can manage is "User 18 edited article 37". There's no real way to get at the username or article title; you can't pass instance data to the attribute because it's baked in at compile time, and I don't really want my logging method to be making all sorts of database calls to get that sort of data, not least because it then becomes impossible (or at least a real pain) to have a single generic logging method.
The alternative to all this is to have a static audit logging class and call something like AuditRecord.WriteLog(foo); all over the place, perhaps with some kind of descriptor class I can use (or inherit from) to describe different types of action, storing all the parameters and generating a description string as needed, but seems less elegant to me; I really like being able to just tag [AuditLog] on top of a method and know that it'll be recorded.
I'd like to avoid huge amounts of conditional logic, like using the controller and action names in some big switch statement to select the correct string template. If I could just get hold of things like article titles in the logging method then it'd be fine. Is there a neat, simple way to do this?
We recently had a similar discussion at work regarding both logging audit history and applying more complex security rules across our new MVC project.
In the end the most "elegant" solution that we came up with was to have the method calls within the controller actions (Your alternative method).
For example:
[HttpPost]
public ActionResult CreateItem(Item item)
{
//Simplified
CheckSecurity(SecurityTypes.ItemCreation);
LogActivity("Created an item");
//Rest of action code
}
This gave us the flexibility to account for all possible use cases, and allowed us to wrap up the logic into simple to use methods to reduce code repetition.
It may be late to answer, but I think there is a good alternative to keep using action filter attributes and to be able to access per-request lifecycle objects.
As anaximander noted it above, the underlying problem is that attributes are resolved by the CLR, so their lifetime cannot be controlled and they don't mix very well with an IoC container (to make them transient, per request instance, etc.).
Usually, in .NET a new instance of attribute is created each time it is resolved by reflection (GetCustomAttribute method).
Furthermore, in the case of MVC/webapi, action filter attributes are cached, so they normally are created just once.
The conclusion is that attributes are designed to annotate only, in other word, they should contain only metadata (they are DTO). Unfortunately, my understanding is MVC and WebApi frameworks are not designed in this way. To restrict action filter attributes to simple DTOs and to be able to manage lifecycle of the logic part around them, special means must be taken.
I think your use case fits perfectly to the solution provided in a Steven van Deursen's great article. It demonstrates how to separate attributes data from logic and it is based on an action filter registered globally, the so called "dispatcher", with the ioc container as a dependency.
The container is not resolved statically. It is provided in the constructor of the global filter when it is registered at the application initialization.
So each time it is executed, it looks for any attribute marker on the action being executed and it resolves a generic interface where the attribute is the generic parameter. Instead of having an action filter attribute which merge data and behavior, you end up using two classes: a plain old attribute - the marker - and the corresponding implementation of the generic interface for its logic counterpart. The container is used to resolve the generic interface. If your filter depends on per-request components, you can create an implementation of the generic interface with the services you need. If it does not depend on other services but you need a per-request lifetime (to measure time between the beginning and the end of an action for example), it also does the job, thank to the use of the container to resolve the generic interface. The aforementioned article contains code examples for WebApi, MVC and ASP.NET 5.
Also, Mark Seemann has made an article on the same approach.
I think it does not provide a good solution for all cases, like authorizations filters and perhaps exception filters, but to me it is the most elegant way for many action filters.
The better way would be to format this data when you view it, rather than build these things during the logging process.
If the action is "login", and the recorded user is available (which you should do) then you build that message in the viewer.
So you log all the raw events, then build the "view model" or "read model" based on this data that is more descriptive. this can allow you to even re-parse all the raw data if you want to change it's description. You could log a lot of data that isn't used yet so you could implement it later within the description.
IMO, sprinkling methods this way inside actions doesn't seem like a good idea and an Action Filter on the controller or base controller is cleaner. if you wanted to do that you could use an AOP (aspect oriented programming) framework to avoid cross cutting...
I am implementing an infrastructure for access control of models in a web application. The library has a context class that controllers (and maybe views) use for determining if the current user has access to a certain object. For keeping relevant information close to the target object, I've decided to pass on the access check request to the models themselves from the context object.
Implementing this mechanism for model object modification is almost trivial. Declare an interface, say, ICheckModifyAccess; and implement it in your model. The same goes for delete check. In both these cases, it is possible to ask an instance of a model whether it is OK to modify or delete them.
Unfortunately, it is not the case for read and create operations. These operations require that I ask the question to the model class. So using an interface for this is not an option.
I ended up creating an attribute, CheckCreateAccessAttribute, and then ended up using this attribute to mark a static function as the interface function. Then, in my context object, I can use reflection to check if such a marked function exists, if it matches the signature I expect, and eventually call it. In case it makes a difference, the method for create access check is public bool CanCreate<TObj>();. A typical model that supports access control would add something like the following to the class:
[CheckCreateAccess]
public static bool CanCreate()
{
return true;
}
I am not very fluent in C# yet, and I have a nagging feeling that I'm doing something wrong. Can you suggest a more elegant alternative? Especially, can you get rid of examining TObj by reflection?
It sounds like you've combined concerns in your object classes instead of separating them.
The temptation to "keep relevant information close to the target object" has perhaps led you to this structure.
Perhaps you could instead handle permissions in a separate class, see for example this article.
I think you shouldn't ask some specific user whether you can modify him (unless the modify right is per concrete entity). Just create a class that handles the rights (or use appropriate existing class).
This would eliminate your need for static classes and reflection.
If you are going to have lots of types, with custom rules (i.e. code) for every one of them, you could have a generic abstract type (interface or abstract class) that is able to check the rules for one type and some repository to retrieve the specific instance.
We have an MVC app that injects our content into a HTML wrapper which supplied by the client.
There are multiple wrappers, such as fund.html, share.html, factsheet.html, and home.html
The wrapper is stored on our webserver. We need to load the wrapper into Site.Master and inject our content into the wrapper's content area, and then render the page.
Basically, I need some advice on how to determine which wrapper to use.
At first, I was thinking that we could map a wrapper to a Controller. So, if we're rendering a View on FundController we could use the wrapper Fund.html, and if it's ShareController, we could use Share.html. In BaseController, which is implemented by both FundController and ShareController I was getting the name of the Controller and using that to load the file, and all was good.
But as requirements changed, it became apparent that this won't work because sometimes we need a controller to render different Views which use different wrappers. So FundController might now have to render Fund.html & Factsheet.html. Now, the Controller doesn't map directly to a wrapper file.
I then thought that I could use the Action name instead of the Controller name to determine the wrapper I should use.. such as public ViewResult Fund() would correspond to Fund.html, and public ViewResult Factsheet() would correspond to Facthseet.html, but this is not ideal because the method that fires in BaseController will fire for all action methods that I execute, including those that return PartialViews and other Action Results, for which I don't want to load wrappers. I only want wrappers for ViewResults.
So, this being the case, I was wondering how best to determine which wrapper to use for which ViewResult I'm executing. One option is using a 'magic string' which, whenever a given Action Method is executing it sets a property in BaseController which can be used to determine the wrapper to use.. but I don't like magic strings. I'd prefer to avoid a hacky approach.
I was also thinking of using an Action Filter which could do the work of loading the wrapper associated with whichever Action Method the filter is associated with. But before doing this, I'd like to get the opinion of other people who may have had to deal with an issue similar to this before. Or if anyone could advise on a better approach to take? What is the best way for me to go about doing this? Thanks.
It sounds like you've already spent a good amount of time thinking about the best way to handle this. Perhaps just combining your existing ideas:
By default, controllers & actions will retrieve their wrappers based on convention. FundController uses the Fund.html wrapper, and ShareController uses the Share.html wrapper.
But also allow for the override of wrappers on a per-action basis, using an ActionFilter.
Barring additional requirements changes (multiple wrappers in multiple content areas within your Masterpage, for exampl), this should cover your needs, no?
I think your Action Filter is one option, or you might want to Extend your very own ViewEngine that is responsible for deciding when to use the wrapper, and when not to.
http://www.singingeels.com/Articles/Creating_a_Custom_View_Engine_in_ASPNET_MVC.aspx
Hope this helps...
I think it might be nice to mimic the rules of views. There is a rule where to look for views, but you can also state the viewname in the action.
The nice thing would be that developers had the same set of rules.
I dont know how you can implement this but I guess its possible.