We have a situation where we need a read only version of an edit page. This is permission based as well as based on the status of the object. My thought is to separate this out into a completely new view but the other opinions are to place this logic in the edit view.
Some information about how the view is structured:
Form elements
Editor templates
Partial views
Kendo controls (fluent wrappers)
So in order to complete the task at hand means the read only functionality needs to exist in multiple places and must be passed to editor templates / partial views by view data.
There is also HTML helpers / extensions that are being used on the page which means updating these too.
Lastly, with the Kendo controls, a lot of the logic of the grid (in-line editing functionality) logic exists in external JS files so we have yet another place to modify the code.
My question is what is the 'best practice' in this regard?
Do we duplicate mark-up (cshtml) by separating the read only view from the edit view.
Or do we change the edit view to accommodate the read only functionality?
It just seems like changing the edit view will add a whole lot of complexity and dependencies for such a trivial task.
You can share the single view for readonly and editable elements by using razor conditioning in the view, But it seems to complicated to manage if the view content complex processing or elements, I recommend you to use separate view and send the appropriate view from the controller's action method depends on your criteria.
You can also use Html.EditorForModel directly to render elements as per your model data annotations OR Html.DisplayForModel to render all model properties for read only purpose.
Related
I have a New and Edit view that basically contain duplicate cshtml. What's the most efficient way to refactor so I can stay DRY?
I already looked through Stack Overflow, and all the answers I could find were for .NET Framework. I wanted to see if there are more efficient ways to reuse code now, with ASP.NET Core.
Is using a Partial View or a View Component the most efficient method? Or is there another ASP.NET Core specific way to handle this?
Partial Views and View Components both allow you to centralize your views, and in that regard are interchangeable. Partial Views, however, exclusively contain view information (i.e., a cshtml file). By contrast, View Components additionally allow you to define preprocessing logic (similar to an [HttpGet] controller action).
Data Access and Parameterization
It's important to note that both Partial Views and View Components can have arguments or values passed into them.
In a Partial View, this is done by relaying either a ViewDataDictionary or a custom view model to the Partial View (reference); this can be done using either the PartialAsync() HTML Helper or by using the <partial /> tag helper's model or view-data attributes.
In a View Component, this is done by defining parameters on the InvokeAsync() method, and then relaying those as either an anonymous object via the InvokeAsync() HTML Helper or as attributes on the <vc:[view-component-name] /> tag helper.
As a result, both approaches can be parameterized and/or data bound, thus allowing them to be respond to the current state.
View Component Specific Capabilities
Where View Components distinguishes themselves is in that ability to define preprocessing logic via the InvokeAsync() method before returning a view model to the view, potentially including access to classes registered via dependency injection (e.g., via a composition root or a dependency injection container).
This is especially useful if your view needs to access data that's not (conveniently) available in the parent view—e.g., via a dependency, a database, or a webservice. So, for instance, if your view component is used by dozens of different views, but always needs access to similar data, this can allow you to centralize that logic so you don't need to look it up in each controller.
Examples: Given the ability to lookup data as part of a view component, I frequently use them for site navigation. That way, I don't need to lookup the navigation data in every single [HttpGet] action, nor include it in every single view model; it can be self-contained. Similarly, I use it for views containing common lookup data, such as dropdown boxes bound to data retrieved from an API or database call.
The Most Efficient Method
As far as which is most "efficient", that is a fairly subjective question, and not one we can answer without more information about your use case.
If a Partial View satisfies your needs, however, it is certainly the simplest and easiest approach: A View Component necessitates that an additional class be created and registered in order to support your view.
The question here, though, is likely less about efficiency and more about your requirements. If your view needs additional preprocessing to e.g. modify the view data, construct a new view model, or collect additional data, then you should use a View Component; otherwise, prefer a Partial View.
That said, given that you're looking to centralize the markup between a New and Edit view, I would expect a Partial View to satisfy your requirement. Both views will likely share an existing view and binding model, and the data populated will be specific to each view, therefore there likely isn't much need to centralize any pre-processing logic.
The one potential exception is if your New and Edit forms include lookup data—such as dropdown lists—sourced from a database. That said, as these views are almost certainly being returned from the same controller, you can easily centralize the lookup of that data in the controller itself, without needing to rely on a View Component to do that for you.
The best way to go about it is to use partial views!
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-6.0
I'm currently working on asp.net core mvc project. There is a main page (cshtml), which contains some data and two partial views in it.
Controller of this page contains action, which returns model to the view (With model binding). I've guessed that 2 more actions in the controller created to return data to both partial views would work just fine. But now my application is not working, because it is trying to pass data from main page to the partial views, creating a binding error (Partial views both has their unique models).
I'm currently using <partial> tag to add my partial views to the main view. This tag contains a property view-data which would resolve the problem with model binding. But it feels like creating a big union object with a lot of sub-objects to pass it through view-data wont be a good practice.
So i'd like to have an opinions on best practices with handling this kind of cases. What is the best way to create pages with multiple separated data like this?
My current opinion is that the best way is to make main view get viable information from the controller and in partial views make it through ajax. But anyway, there is still a question how to bypass this error with the application trying to pass data from main view to partial view (Like if i want to keep model binding in partial view to fill it with ajax).
So after some research i came to the conclusion and found a solution for my problem. PartialViews is not made for such cases. PartialView always depends on model information coming from its parent View.
Instead, if you want to achieve the same kind of behavior as i do you should use ViewComponents. It is completely independent tool which has an ability to make its own data access and build whatever model it needs. You also can access ViewComponent anywhere in your views even layouts, and even pass parameters to it by name.
I hope anyone finds this article helpful. Here is official guide by msdn on how to implement and use view components
I’m refactoring a big view model and it's associated XAML page. I use Prism. The main page has a clear functionality, create an avatar. There are steps to create the avatar like take the picture, edit the picture, etc. I have now a detail side bar which controls the navigation for the steps and a main content area which I show different content depending on these steps. I hide/show the appropriate views depending on the step. The project grew and now I have a 2000+ line view model and a huge XAML file.
What I ended up doing after some research is creating ContentViews for each step (showing and hiding them for each step again), so the XAML get's modularized for each step and also a View Model for each step. I was successful in binding the ContentView to each ViewModel but now I have problems communicating the different View Models information.
As before everything was in the same View Model, all views could share the same bound properties if needed. Now, as each view model is independent I need to find a way to properly share this information. My first approach was to use the Messaging Center. This way I can send the information i need to share to the view model that manages the navigation between steps (NavigationViewModel) and this can send this information to the following view models.
The thing is that I don't really like this solution as I find it too complex and will end up with a lot of code in the NavigationViewModel to subscribe/send to each sub-viewmodel to pass the shared information.
So my question is, do you know any other way to ease the communication between the view models?
I even thought about using partial classes to 'hide' my big view model complexity, but I think this is not a good idea.
Recenlty i came across the same problem,my ViewModel became really huge(with hundreds of properties) .So what i did is :
Created an Interface class.Putting all the common properties in there.Let's say IA.
Created another class inheriting IA.
And now multiple classes are inherting IA,reducing the overall properties numbers.
I am using MVC 5 controller with views,using entity framework and create, delete, details, edit, index cshtml pages occurs automatically. When I change the model classes and update the database CSHTML pages don't change. I am manually deleting view pages and recreating them with scaffolding. When I do these things my HTML designs are deleted.
How can I update aspnet-scaffolding cshtml pages automatically?
Note: I am using layout pages but they aren't solving my problem.
"When i do these things my html desings are deleted. "
Here is the root of the issue. If I understand you correctly you are:
Using scaffolding to generate Views.
Modifying the CSHTML of those views to customize the View.
Your hope is that after you modify the database, the scaffolding will update the views. However, when it generates the new CSHTML Views, how does it know how to combine the changes with your customizations? It doesn't. It can't know how to generate a completely new view and somehow integrate your customizations.
This is pretty much the same with any scenario that involves code generation. You have to make a choice. If you want to preserve your edits, you can no longer use the scaffolding to generate new views after editing. If you want to benefit from scaffolding after database updates, then you should never edit the CSHTML with the intention of customizing it.
I used scaffolding a long time ago only as a learning tool, to see how things like lists were handled. For probably 2 years I have never used scaffolding, and it is generally slow for larger projects, so I just always create an empty CSHTML or copy an existing one that is close to the approach I will take with the new one.
I would instead focus on other techniques that will help make creating CSHTML easier.
Using partial Views appropriately to pull reusable UI elements out.
Use Custom Object Templates to customize the results of things like DisplayFor and EditorFor.(I personally don't do this but I've seen others use it effectively)
Implemented helpers to take in parameters and produce HTML that fits the patterns you follow. Since I use bootstrap I created my own Html.LabelForBootstrap helper for example, that outputs HTML formatted for use with bootstrap with bootstrap classes.
Effective use of Layout pages and sections.
Eventually you will begin to see that the scaffolding isn't at all appropriate in many cases. E.g. the UI for relating one entity to another, the fact that it shows all columns when many aren't appropriate for display, etc.
You might be interested in Dynamic Data. It is more convention oriented in that it determines UI from database structure, but you provide customization conventions. Overall it's not really different conceptually from using MVC with Custom Object Templates:
http://msdn.microsoft.com/en-us/library/vstudio/ee845452(v=vs.100).aspx
Dynamic Data isn't mainstream, and skills you learn from using it probably aren't very marketable. It is probably only appropriate for administrative interfaces where user experience isn't a primary concern. Once you learn MVC really well you can pretty quickly spit out basic UI for new entities, so I don't recommend Dynamic Data.
It is possible to modify the default scaffolding templates. So if you wanted to, you could customize the template and have it generate your views. You will quickly run into the same issue however, as you will encounter a scenario where your generic template doesn't satisfy and you need to customize the output View CSHTML, but now you can no longer regenerate the View so the scaffolding template has limited usefulness:
http://www.hanselman.com/blog/ModifyingTheDefaultCodeGenerationscaffoldingTemplatesInASPNETMVC.aspx
I am using ViewModels with asp.net MVC3. One of the thing I am curious about is, suppose I have an entity named Customers and it has Add, Edit, Delete screens. Assume that they all have different properties requirements.
For eg. Add may have address field but the edit screen may not have edit screen, delete may only use customer name more than anything else.
My question is, how do you create ViewModels for this? Do you go with the approach of shared ViewModels between add, edit and delete i.e a single viewmodel class that handles all for you or do you prefer to create viewmodels classes / page?
Advantage with shared viewmodel is it reduces development time and we can reuse classes. But big problem with this is that if you are using tool like Automapper you may expected results for different screens.
Disadvantage with one viewmodel/page is that it increases development time. Which way should I go?
My approach to view models is to use shared view models until the requirements (the data transported) to the view is different. That means I'm using a shared view model for example for CreateAddress and EditAddress in case all data transported to the view is the same. In case an additional field needs to be displayed in the view for example in the CreateAddress view I'm refactoring my view models and using different view models for CreateAddress and EditAddress.
For example for DeleteAddress I'd use a distinct view model from start because I know that the data displayed in the DeleteAddress view is almost never the same as in Create/EditAddress.
Another approach is to use dynamic view models, since view models should/must not implement business logic and act as DTOs between controller and view this approach has some benefits (No need to create logic free, throw away DTOs).
It depends upon situation. if you have similar requirements for different screens (validation, properties to render etc.) you can use the viewmodel across different views. If there is difference of one or two properties, i would still use the same viewmodel and where these properties are not needed i will put them in hidden inputs so they travel back with the form post not allowing unwanted results. Hidden fields, as all know, can be tweaked and its upon developer to decide if it is safe to use hidden fields. However, if i have different validation requirements for two screens then i definitely have to go with viewmodel/page approach. You can mix both approaches according to requirements as they say "there is no best way of doing things"
All fields that exists in a model can be changed. It doesn't matter if they are hidden or not. All the user has to do is to inspect your pages and try to figure out what fields exist in the model.
Then he can add those fields (for instance with Chrome Dev Tools) to make changes to them.
The safest way to get rid of that problem is to just have models that only have the fields that are allowed to be changed.
That said, go ahead and use the same model if all fields in the model should be allowed to be changed by all users. (And simply do not show the fields that should not be modified)