MVC with razor in Sitefinity 5

Posted by Community Admin on 04-Aug-2018 15:43

MVC with razor in Sitefinity 5

All Replies

Posted by Community Admin on 16-Mar-2012 00:00

I've managed to get MVC + razor working in Sitefinity 5 so I though I'd share how.

I wanted to use MVC + razor for my frontend widgets. I've tried it in Sitefinity 4 but wasn't able to get it to work. Well, it will if you are already logged in. You can't use MVC and login simultaneously in Sitefinity 4. Though the login will work again if your remove the _AppStart files. Though they don't work together because authentication is forms based, it says so in the web.config file, so if one were to somehow get around that it could work.

Anyway, since Sitefinity doesn't support razor widgets I'm using iframes to render my MVC widgets. So it's not a real solution, more like a hack. But you can also use it to have parallel MVC sites along with Sitefinity ones. So I guess it's a solution for that.

 

Hopefully I haven’t forgotten anything in any of the steps.

-         First create a fresh MVC3 project

-         Look at it's references

-         References that it has and your Sitefinity project doesn't just add to your Sitefinity project’s references. Here’s a list of the references I see in a fresh MVC3 project:

 

EntityFramework
Microsoft.CSarp
System
System.ComponentModel.DataAnnotations
System.Configuration
System.Core
System.Data
System.Data.DataSetExtensions
System.Data.Entity
System.Drawing
System.EnterpriseServices
System.Web
System.Web.Abstractions
System.Web.ApplicationServices
System.Web.Dynamicdata
System.Web.Entity
System.Web.Extensions
System.Web.Helpers
System.Web.Mvc
System.Web.Routing
System.Web.Services
System.Web.WebPages
System.Xml
System.Xml.Linq

-         I forget which ones I had to add to the Sitefinity project.

-         Then you do a similar thing for the web.config file, you add parts that are missing. But not all of them. Like membership management and so on. These are the parts I added:

<configuration>
    ...
    <appSettings>
        ...
        <add key="webpages:Version" value="1.0.0.0" />
        <add key="ClientValidationEnabled" value="true"/>
        <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
        ...
    </appSettings>
    ...
    <system.web>
        ...
        <compilation ... targetFramework="4.0">
            ...
            <assemblies>
                ...
                <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                ...
                <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                ...
            </assemblies>
            ...
        </compilation>
        ...
        <pages>
            ...
            <namespaces>
                <add namespace="System.Web.Helpers" />
                <add namespace="System.Web.Mvc" />
                <add namespace="System.Web.Mvc.Ajax" />
                <add namespace="System.Web.Mvc.Html" />
                <add namespace="System.Web.Routing" />
                <add namespace="System.Web.WebPages"/>
            </namespaces>
            ...
        </pages>
        ...
    <system.web>
    ...
    <runtime>
        ...
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            ...
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
                <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
            </dependentAssembly>
            ...
        </assemblyBinding>
        ...
    </runtime>
    ...
</configuration>

-         Then in your Sitefinity project create two empty files:

 

_AppStart.cshtml

_AppStart.vbhtml

 

-         Then copy paste the global.asax files from the MVC project to your Sitefinity project

-         You’ll have to edit the global.asax file and change it’s inherits attribute so that it’s your project. For example my global.asax is

<%@ Application Codebehind="Global.asax.cs" Inherits="SitefinityWebApp.MvcApplication" Language="C#" %>

-         And you’ll have to edit the global.asax.cs file to register your MVC routing

-         Now regarding this, I’ve configured it so that I hold all of my MVC widgets in the “Areas” section/folder. You could add the standard MVC folder structure to your Sitefinity project and route to files in it. I don't as I find this cleaner. Especially since I'm only interested in MVC widgets.

-         Anyway, this is my global.asax.cs file:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Telerik.Sitefinity.Abstractions;
 
namespace SitefinityWebApp
    // Note: For instructions on enabling IIS6 or IIS7 classic mode,
 
    public class MvcApplication : System.Web.HttpApplication
    
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        
            filters.Add(new HandleErrorAttribute());
        
  
        public static void RegisterRoutes(RouteCollection routes)
        
            routes.IgnoreRoute("resource.axd/*pathInfo");
        
  
        protected void Application_Start()
        
            AreaRegistration.RegisterAllAreas();
 
            Bootstrapper.Initialized += new
            EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized);
 
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        
  
        void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        
            if (e.CommandName == "RegisterRoutes")
            
                AreaRegistration.RegisterAllAreas();
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
            
        
    

-         And then change your Sitefinity project to a MVC project

-         It’s basically the same as with the references and the web.config file

-         You open the folder where the csproj file for your Sitefinity project is and open it in a text editor, notepad(++) for example

-         Open the csproj of the fresh MVC project and find what your Sitefinity projects lacks and add it

-         This is what I added to my Sitefinity project, minus the target-after-build which was already there:

<Project ... >
    <PropertyGroup>
        ...
        <ProjectTypeGuids>E53F8FEA-EAE0-44A6-8774-FFD645390401;...<ProjectTypeGuids>
        ...
        <MvcBuildViews>false</MvcBuildViews>
        ...
    </PropertyGroup>
    ...
    <Target Name="AfterBuild">
    </Target> -->
    <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
        <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
    </Target>
    ...
</Project>

  

-         Now you can create an area. You go into your Sitefinity project in Visual Studio -> click on it -> Add -> Area and add an area.

-         You have to manually create the controllers and views in it so I just copy paste them from a MVC project.

-         I don’t think you can copy paste your MVC project into the Areas folder. I tried it and the web.config file of the MVC project was causing me problems so I decided to just copy paste the relevant parts.

-         Now, I have a problem when trying to create controllers with read/write + views. It says something like some assembly is missing or it’s dependencies.

-         You can fix this by installing the full package of the assembly for the project, for example the Ajax Toolkit with nuget.

-         At least I think so. One assembly, Microsoft.IdentityModel, it's package cannot be installed on Win XP, which is the platform I am using, so that’s where I stopped with that issue.

-         Now, the MVC widgets in the Areas folder can be used independently of Sitefinity, you can navigate to the MVC pages, use them side by side with Sitefinity's pages if you wish to

-         But to use them inside Sitefinity as a widget I create a .ascx file with an iframe

-         Which I register in Sitefinity as a regular widget

-         Regarding iframes there is an issue with them not resizing properly

-         Add this javacript to fix it, for example in the master page of the template you are using

<script>
    function resize(elem)
        var outer = elem;
        var inner = elem.contentDocument.documentElement;
        outer.style.border = "0";
        outer.style.overflow = "hidden";
        outer.style.height = Number(inner.scrollHeight + 10) + "px";
        outer.style.width = Number(inner.scrollWidth + 10) + "px";
    
</script>

-         And for the iframe, let’s say you have an area named “Test” with the file "Test.ascx" with the iframe:


<iframe class="mvc-frame" onload="resize(this)" frameborder="0" id="MvcIframe" src="/Test"></iframe>

 

-         The widget with this iframe should now, when loaded inside a Sitefinity page, display your MVC pages in the Test area as a properly sized iframe.

Posted by Community Admin on 03-Apr-2012 00:00

Figured out how to use MVC directly, without the need for iframes.
The issue is that Sitefinity pages do not inherit from System.Web.Mvc.ViewPage so they don't have a view context defined. So you have to make one yourself. But you still need a .ascx file as an entry point for a Sitefinity widget. Here's an example of a widget I use:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
 
<%
    ControllerContext controllerContext = new ControllerContext(
        HttpContext.Current.Request.RequestContext,
        new TheNameOfMyControler() as ControllerBase
    );
 
    ViewContext viewContext = new ViewContext(
        controllerContext,
        new WebFormView(controllerContext, "~"),
        new ViewDataDictionary(),
        new TempDataDictionary(),
        controllerContext.HttpContext.Response.Output);
    viewContext.RouteData.DataTokens.Add("area", "NameOfMyArea");
    viewContext.RouteData.Values.Add("controller", "TheNameOfMyControler");
 
    ViewPage page = new ViewPage();
    HtmlHelper Html = new HtmlHelper(viewContext, page);
    AjaxHelper Ajax = new AjaxHelper(viewContext, page);
%>
 
<% Html.RenderAction("NameOfMyAction"); %>
The MVC views in this widget will always render inside the widget space, automatically resizing it appropriately.

I also changed my master to inherit from System.Web.Mvc.ViewMasterPage.

This thread is closed