Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC : Good Replacement for User Control?

I found user controls to be incredibly useful when working with ASP.NET webforms. By encapsulating the code required for displaying a control with the markup, creation of reusable components was very straightforward and very, very useful.

While MVC provides convenient separation of concerns, this seems to break encapsulation (ie, you can add a control without adding or using its supporting code, leading to runtime errors). Having to modify a controller every time I add a control to a view seems to me to integrate concerns, not separate them. I'd rather break the purist MVC ideology than give up the benefits of reusable, packaged controls.

I need to be able to include components similar to webforms user controls throughout a site, but not for the entire site, and not at a level that belongs in a master page. These components should have their own code not just markup (to interact with the business layer), and it would be great if the page controller didn't need to know about the control. Since MVC user controls don't have codebehind, I can't see a good way to do this.

Update FINALLY, a good (and, in retrospect, obvious) way to accomplish this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace K.ObjectModel.Controls
{
    public class TestControl : ViewUserControl
    {
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            writer.Write("Hello World");
            base.Render(writer);
        }
    }
}

Create a new class which inherits ViewUserControl

Override the .Render() method as shown above.

Register the control via its associated ASCX as you would in a webForm:

<%@ Register TagName="tn" TagPrefix="k" Src="~/Views/Navigation/LeftBar.ascx"%>

Use the corresponding tag in whatever view or master page that you need:

<k:tn runat="server"/>

Make sure your .ascx inherits your new control:

<%@ Control Language="C#" Inherits="K.ObjectModel.Controls.TestControl" %>

Voila, you're up and running. This is tested with ASP.NET MVC 2, VS 2010 and .NET 4.0.

Your custom tag references the ascx partial view, which inherits from the TestControl class. The control then overrides the Render() method, which is called to render the view, giving you complete control over the process from tag to output.

The difference between using this approach and calling Html.RenderPartial() or `Html.RenderAction()' is adding the control to a view is done with a webforms-like tag, which is not only more comfortable for designers, but keeps them from having to be aware of controller names and methods. The name of the control class is isolated to the ASCX, also making it easier to drop these in an assembly and reuse them across separate projects.

Some may say that this violates SoC, but I believe that this approach is functionally equivalent to tying a partial view and a controller together while maintaining clean markup. It should be clear, however, that it is still up to the developer to keep only presentation-related logic in the control Business and data access logic still belong in their respective layers.

like image 904
3Dave Avatar asked May 10 '10 16:05

3Dave


People also ask

Can we use user control in MVC?

In ASP.Net you need to register one tagprefix and then use the user control by tagprefix registered but in ASP.Net MVC using simple Thml. RenderPartial we can use the user control.

Is ASP.NET MVC outdated?

ASP.NET MVC is no longer in active development.

Is ASP.NET better than MVC?

MVC is lightweight framework with clear separation between code and HTML. It has following major benefits. Business logic is stored in a single state called model where in traditional asp.net platform, each page has its own business logic making it complex.


1 Answers

I'm a little confused here.

First of all, the .NET MVC equivalent to User Controls is Partial Views. Partial Views are a convenient way of encapsulating common View functionality in a single location. You can then call a Partial View from inside another View.

Second of all, modifying a View shouldn't mean also modifying a controller. If you are required to make a change to both just because your View changed (and not the underlying data), then there's a code issue somewhere along the line.

like image 194
Justin Niessner Avatar answered Oct 08 '22 05:10

Justin Niessner