I've made an Area project for my ASP.NET MVC application called 'Admin'.
This will contain all the logic for the Administration section of the site, where the users can add/remove pages, etc.
There's a menu at the top, of things the user can manage. (E.g. 'Content', 'Users', etc)
For each of these, I'm making a controller ('ContentController', 'UsersController', etc)
I'm wondering how to setup the navigation, as there seem to be varying approaches.
One approach is to use MvcSiteMap, which involves creating a '.sitemap' file and decorating actions on my controllers with an 'MvcSiteMapNode' attribute.
The problem with the above is that it's complicated to implement (especially in an Area project, because of the way Areas work in ASP.NET MVC). It also seems like overkill.
I've come up with a different way, which is to decorate each controller with my own attribute. Then I have a helper method that renders my navigation by using reflection to loop through every controller, pick out the ones that have that attribute, and then add them to the navigation menu.
What are your thoughts on the above method? Can you think of an even simpler way of doing this?
So I've done it my way - an attribute on each controller, then a static method that reads all the attributes on application start (using reflection) and keeps them in memory.
So far this has worked perfectly, and I haven't needed any of the advanced features of MvcSiteMap.
Related
Is there any library / framework that could simplify Universal Windows Platform app development of the application that contains multiple Frames.
I mean, using MVVM Light or BezySoftware MVVM-Navigation the application is highly tied to the idea of navigating between different pages that are hosted by single frame.
The UI I try to develop consist of multiple content frames (main, left, right) which content varies. I need something that will let me navigate easily between different views (by placing these views into appropriate frame) and provide the same features I would have with BezySoftware MVVM-Navigation, so:
handling of the view model state persistence
the ability to activate / query deactivate view models
back button feature
Few different options:
Combination of a single navigation service injected into your view model AND user controls for areas that need to be repeated view to view (e.g. a tabs, status bars, etc). With this route, every time you create a new view you would paste in the common user controls that need to appear. You would also be able to expose bindable properties from said user controls.
Combination of ContentControl, DataTemplate, and DataTemplateSelector to load in either an entire view (Page) or fragments of XAML. As one person pointed out you cannot use DataType attribute, instead you use the DataTemplateSelector class to do the mapping for you. With this approach you can also use triggers to dynamically change the template (content) based on changes to properties on your view model and/or user interactions.
A mix between 1 and 2 above.
I might right the whole thing right here, but it too lengthy. I just recommend you see this article to get your answer.
MVVM patter in UWP
I am loading controls dynamically from the web server from separate XAP files. After creating an instance I want to show them in tab Pages. The controls can be MMVM controls using CM but also non MVVM standard controls.
Before trying the tab I tested to simply show a control dynamically on the page by using:
<ContentControl Name="TestControl" />
Test control is a property of Type UserControl which is set via creating a new Instance of a dynamically loaded control. Now this gives me an error that it can't find the view. In case of non MVVM controls there is of course no view, so how do I load a non MVVM control?
I tried to make the test control a MVVM control, but still get the cannot load view error. Makes sense as such instance is not created. If I create an instance of the dynamically loaded view besides the view model, how do I "Add" this so that CM finds it?
Last but not least, how do I bind this to a tab control in Silverlight? The idea is to have a collection of user controls (plugins) which each is rendered in its separate tab page.
Thanks for any help.
(I got this done in no time NOT using MVVM, still not sure if MVVM is worth all the complexity)
There's no such thing as "mvvm control". MVVM is just a pattern not a control type. Basically, in Caliburn you don't need to work vith UserControls or Views directly, but if you pick the ViewModel first approach, Caliburn framework should be able to find the matching view for you. In your case since you're loading XAP files dynamically, you need to add them to the list of assemblies Caliburn looks to find a View/ViewModel (and bind them together) and this is done through IAssemblySource interface. According to the documentation here:
So, what is AssemblySoure.Instance? This is the place that
Caliburn.Micro looks for Views. You can add assemblies to this at any
time during your application to make them available to the framework,
but there is also a special place to do it in the Bootstrapper.
Having worked with .net in both winforms and ASP.net for a few years I am now starting to get into MVC (a little late I know). One major confusion for me is the concept of reusable 'components', similar to the concept of a usercontrol in webforms.
For example, I would like to have a number of 'widgets' within the members area of my site, one of which is the details of the logged in users account manager. I can create this as a partial however when the page loads the data needs to be passed in as part of the ViewModel / View Data. I would like to use this widget in a number of different sections which would then mean that I need to put the code to pass the data in into a number of different controllers. This seems to violate the DRY principle, or am I missing something here? I would ideally like everything to be encapsulated within the 1 partial which can then be used in any page.
You can go three ways:
1) For simple controls without much logic, you can create new instance of the custom view model for the control:
Html.RenderPartial("YourControl", new YourControlViewModel () { Param1="value1", Param2 = Model.AnotherValue });
2) If you need some back end logic for the control, you can use
Html.RenderAction("ActionName", "SomeControllerName", RouteValuesDictionary);
It will call standard controller action, use the view, and insert the resulting output back to the page. You can add [ChildActionOnly] atribute to the controller method to ensure that the method will be available only from the Html.RenderPartial. It is slightly violating the MVC principle (view shouldn't call controller), but its great for widgets, and it is used in the Ruby on Rails world without much issues. You can check great article from Haacked
3) Create custom html helper for tasks like custom date formatting, calculating etc..
In your case, I would choose the number two.
I have a layout which works fine. This layout contains several partials, which display adverts, a side column a slideshow, etc. All of these are likely to change depending on which page (module/controller/action) of the site you are on.
What is the best way of doing this correctly? In the past I have assigned variables to my view inside my controllers, these are then passed to the partial which then displays the correct slideshow or advert. This seems ugly and not entirely correct for an MVC application.
Does anyone have any other methods of doing this?
Partials are just another view scripts.
My advice is: newer put your logic into the view scripts. Your may store the logic in:
models (remember, that you can create your own models, extending, or not extending the basic database models, eg. data hydrators)
view helpers (with parameters)
services (dependent on models, returning models)
combination of the above
Then use view helper or pass the ready data (model) to different partials.
Tip: Dependency injection is a good thing.
I'm a beginner with Eclipse RCP and I'm trying to build an application for myself to give it a go. I'm confused about how one actually goes about handling model objects. None of the examples I can find deal with the problem I'm having, so I suspect I'm going about it the wrong way.
Say I need to initialise the application with a class that holds authenticated user info. I used my WorkbenchWindowAdvisor (wrong place?) to perform some initialisation (e.g. authentication) to decide what view to show. Once that's done, a view is shown. Now, that view also needs access to the user info I had earlier retrieved/produced.
The question is, how is that view supposed to get that data? The view is wired up in the plugin.xml. I don't see any way I can give the data to the view. So I assume the view has to retrieve it somehow. But what's the proper place for it to retrieve it from? I thought of putting static variables in the IApplication implementation, but that felt wrong. Any advice or pointers much appreciated. Thanks.
The problem you are facing here is in my opinion not RCP related. Its more an architectural problem. Your view is wired with business logicand!
The solution can be done by two (common) design-patterns:
Model-View-Controler (MVC)
Model-View-Presenter (MVP)
You can find plenty information about this in the web. I am going to point a possible solution for your particular problem using MVP.
You will need to create several projects. One is of course an RCP plugin, lets call it rcp.view. Now you create another one, which doesnt make UI contributions (only org.eclipse.core.runtime to start with) and call it rcp.presenter. To simplify things, this plugin will also be the model for now.
Next steps:
Add the rcp.presenter to the
dependencies of rcp.view (its
important that the presenter has no
reference to the view)
Export all packages that you are
going to create in the rcp.presenter
so they are visible
In rcp.presenter create an interface
IPerspective that has some methods
like (showLogiDialog(), showAdministratorViews(User user), showStandardViews(User user))
Create a class PerspectivePresenter that takes IPerspective in the constructor and saves it in an attribute
In rcp.view go to your Perspective, implement your interface IPerspective, and in the constructor create a new reference presenter = new PerspectivePresenter(this)
call presenter.load() and implenent
this in the presenter maybe like this
code:
public void load()
{
User user = view.showLoginDialog(); // returns a user with the provided name/pw
user.login(); // login to system/database
if(user.isAdministrator())
view.showAdministratorViews(user);
else
view.showStandardViews(user);
}
As you can see, the view just creates a reference to the presenter, which is responsible for all the business logic, and the presenter tells the view what to display. So in your Perspective you implement those interface functions and in each one you can set up your Perspective in a different way.
For each View it goes in the same way, you will need a presenter for the view which performs operations and tells the view (using the interface) what to display and passing down the final data. The view doesnt care about the logic. This is also very usefull when using JFace-Databindings (then only bound data is passed to the view).
For example, the WorkbenchWindowAdisor will just create everything that is needed in the application. Other views, perspectives, then can enable/disable menus and so on depending on the data they got (like when isAdministrator you might want to enable an special adminMenu).
I know this is quite a heavy approach, but the Eclipse RCP is designed for big (as the name says rich) applications. So you should spend some time in the right architecture. My first RCP app was like you described...I never knew where to store things and how to handle all the references. At my work I learned about MVP (and I am still learning). It takes a while to understand the concept but its worth it.
You might want to look at my second post at this question to get another idea on how you could structure your plugins.