How can I use custom controls with ASPNET.MVC Razor?
I want to use a custom control on a Razor view. for instance:
<mycontrols:something>@Model.MyVar</mycontrols:something>
or
<mycontrols:something myattribute="@Model.MyVar" />
Please note that my goal is to use only few controls derived from MvcControl, only for trivial repetive ui stuffs.
I tried to find out a syntax similar to @Register to write on the top of the view, but without any success.
Then I went to the web.config, adding
<pages>
<controls>
<add tagPrefix="mycontrols" namespace="mynamespace" assembly="myassembly"/>
</controls>
</pages>
but it looks like custom controls are ignored in rendering.
Someone could help?
...Might be it is a little bit old fashion, but sometimes also custom control could be useful to make your code cleaner!
The Razor syntax does not support the notion of Controls at all. If you want to use controls you will have to use the ASPX (WebForms) syntax.
However, the recomended MVC pattern is to use html helper functions or partial views. In Razor you can also use the @helper
syntax for quick helper functions.
In ASP.NET MVC custom server controls should be avoided. Most of them rely on ViewState and PostBack which are notions that no longer exist in MVC. You should prefer using templates, HTML helpers to implement some reusable functionality. Another problem with controls is most of them encapsulate some business logic which fetches data from somewhere and renders it which is an anti-MVC pattern. In MVC it is the controller responsibility to manipulate the model and fetch data and pass a view model to the view which simply should display it.
MVC uses partial views rather than custom controls, and they can be used in two ways that cover pretty much everything a custom control can do
- RenderPartial which renders data already retrieved by the page controller
- RenderAction which is similar but has its own controller action so can get data independently
The only scenario I can think of where it would be worth putting a custom control on an mvc view is if you are working on a partially migrated webforms project, and I doubt that would work with anything other than the WebFormsViewEngine.
You can do this, though I don't recommend it, though I'm not here to judge. I might add that I don't expect postback and view state to continue working either but you can at least render all of the html.
The only way to do this is a bit of a hack, because razor doesn't support webforms view engine controls. However, it does support partial views made in the webforms View engine. So a hacky solution is to include a partial view with your control in it as such:
For example, say you want to use the office web ui ribbon in your mvc3 project, you could do so by including
<body>
<div>
@Html.Partial("_RibbonPartial")
</div>
</body>
in your view. Where _Ribbon is of type .aspx
then in your partial view simply use your control and set runat="server" and put it inside of a form with runat="server"
//_Ribbon.aspx
<form id="form1" runat="server">
<XyzControls:Manager ID="Manager1" runat="server" UITheme="Silver" />
<XyzControls:OfficeRibbon ID="OfficeRibbon1" runat="server" ApplicationMenuColor="#267c29"
ApplicationMenuText="Item" ApplicationMenuType="Backstage">
//... rest of control code
</form>
Then you need to use ajax to implement events instead of using postback.
Then to cleanup, get rid of the generated code from webforms view engine for post back that you don't need.. You can try keeping it, I haven't so I'm not sure what will happen. I know there are ways to have a fake viewstate as well if you really want to get into messy hacky stuff, but to remove the extra code from webforms you can use the following jquery:
$(function ()
{
// we don't need any of the webforms stuff
$("#__EVENTTARGET","#aspnetForm").parents("div:first").remove();
$("#__EVENTVALIDATION","#aspnetForm").parents("div:first").remove();
});
I had the same demand. Wanted to use custom webcontrol from Razor/MVC page. One should not do that with controls, that is handling postback. You don't have the eventcycle to support that, but if your only demand is to use a 'rendering control', you could instantiate it in razor, and control where the rendering takes place:
@{
var myControl = new mycontrols.something();
myControl.myattribute = Model.MyVar;
mycontrol.RenderControl(new HtmlTextWriter(this.Output));
}