How would you go about supporting external composable parts in an ASP.NET MVC view?
What do I mean by this? Think either "login box on every page" or "iGoogle". It's stuff that needs to be in certain places that is external to each controller/view.
One approach at this would be adding components in the view like so:
<% foreach (var component in GetComponents()) {%>
<%= Html.RenderPartial(component.ViewName, component.ViewData)%>
<%} %>
In the example above I'm looking for a good way to have the viewname and viewdata delivered by each component's controller and not the controller of the view they are displayed on. Any totally different solution you can suggest would also be of interest. Filters, WebForms, etc.
Update: I'll try to explain what I'm trying to wrap my head around with an example. I'll pick the login functionality.
In a typical webforms application this could be a user control that retrieves the appropriate data in the load event of the page's life cycle and updates some UI controls. Upon click the page would post back and we can act upon the posted information in the click event in the same user control.
As of my current understanding of the ASP.NET MVC style the controller that first accepts the request would retrieve the appropriate data and pass it to the view which in turn would pass it along to the login partial view. The login view would define a form whose post action is directed at the login action of the login controller. The posted information is used by the login action and we can choose to pass the request along to the original controller using some nifty scheme.
I assume there is a smarter approach than the above that doesn't require I put controller logic in a view/a master page.
The component that displays the application's User Interface (UI) Controller. The component that handles user interaction, works with the model, and ultimately selects a view to render and display the UI. Now let's see the the concept of ASP.NET MVC and Webforms, Feature.
So, the _layout. cshtml would be a layout view of all the views included in Views and its subfolders. The _ViewStart. cshtml can also be created in the sub-folders of the View folder to set the default layout page for all the views included in that particular subfolder.
Scaffolding is a technique used by many MVC frameworks like ASP.NET MVC, Ruby on Rails, Cake PHP and Node. JS etc., to generate code for basic CRUD (create, read, update, and delete) operations against your database effectively. Further you can edit or customize this auto generated code according to your need.
The Model-View-Controller (MVC) architectural pattern separates an application into three main components: the model, the view, and the controller.
There is two ways you can do this:
One: Make a BaseController, that allways gets the data needed for these components, set the ViewData["loginbox"] = loginBoxData, and then you can pass it along like so.
<% foreach (var component in GetComponents()) {%>
<%= Html.RenderPartial(component.ViewName, ViewData[component.Name])%>
<%} %>
The problem about this method is that you need to have logic to say WHEN all these data needed for the components is going to be fetched, and when not to.
TWO:
There is a MVC Futures DLL that you can download from here.
It you reference that, and remember to add its namespace to your web.config, then you should be able to say: Html.RenderAction("blah")
- this method makes the full trip by contacting a controller, initiate the view, and returns the HTML.
You could use the master page and use content placeholders for view content pages and view user controls.
The default project template in ASP.NET MVC Framework Beta has a content placeholder for the View Content Page. There is also a View User Control for the login/logout link at the top right corner of the pages.
The view content pages are supposed to be used with the data that comes from the View that you are looking at. I.e. if you're browsing to the Index
action in HomeController
, the server will render the Home/Index.aspx
view content page.
In the master page you need the following line:
<asp:ContentPlaceHolder ID="Holder1" runat="server" />
And in the view content page itself you compose for that place holder with the following:
<asp:Content ID="Content1" ContentPlaceHolderID="Holder1" runat="server">
<p>This text goes to "Holder1" content place holder and
I can access the ViewData.</p>
<p><%= ViewData["Message"] %>
</asp:Content>
Each asp:ContentPlaceHolder
corresponds to the view's asp:Content
through the id. So if you want several placeholders like this:
<asp:ContentPlaceHolder ID="Holder1" runat="server" />
<asp:ContentPlaceHolder ID="Holder2" runat="server" />
…you can handle them in the view content page like this:
<asp:Content ID="Content1" ContentPlaceHolderID="Holder1" runat="server">
<p>This text goes to "Holder1" content place holder</p>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Holder2" runat="server">
<p>This text goes to "Holder2" content place holder</p>
</asp:Content>
View user controls can be used regardless of what view you are looking at. Here are some examples of viewing user controls, are taken from Wekeroad's blog post about View User Controls. To use a view user control:
<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”)%>
If you have the need you can also pass data and anonymous types to it.
<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”,ViewData.Users, new {GroupID=2})%>
without understanding the question properly, i'd suggest a masterpage approach. ie. have the masterpage render the components and pages derive from the masterpage.
i fear this is not a good answer however. i dont understand this: "..have the viewname and viewdata delivered by each component's controller and not the controller of the view they are displayed on."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With