1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / MVC with razor in Sitefinity 5

MVC with razor in Sitefinity 5

2 posts, 0 answered
  1. Bozidar
    Bozidar avatar
    2 posts
    Registered:
    04 Jan 2012
    16 Mar 2012
    Link to this post

    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.

  2. Bozidar
    Bozidar avatar
    2 posts
    Registered:
    04 Jan 2012
    03 Apr 2012
    Link to this post

    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.

2 posts, 0 answered