Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.


Module Development in DNN 8: 2 - Creating your first MVC Action/View

In my previous blog I reviewed the development environment I will be using for my blog series on Module Development in DNN 8.  As a reminder you can find all the sample code on Github at https://github.com/cnurse/DnnConnect.Demo. In this blog we will create our first  MVC Action and View.

The Model

As mentioned in my previous blog I will be describing how to create a module to manage contacts on my site.  The Contact List module will be scoped to the portal – i.e. all contacts for a portal will be available in any instance of the module.  A Contact will have 5 simple properties:

  • First Name
  • Last Name
  • Email Address
  • Phone Number
  • Twitter Handle

As the domain is not what we are really focusing on in this series I have kept it simple.  As we will be creating both an MVC module (as well as a SPA module in future blog posts) I have created a separate project for the Model (API) located in the Dnn.ContactList.Api project (Figure 1).

Figure 1 – The Model project

 

The Api uses the DAL 2 data access layer and implements a simple “Repository” facade over that framework.  As with many of DNN's APIs the ContactRepository is implemented using the ServiceLocator pattern so the methods can be Unit Tested.

The IContactRepository interface provides a simple CRUD API, as shown in Figure 2.

Figure 2 – The IContactRepository interface

   1:  public interface IContactRepository
   2:  {
   3:      int AddContact(Contact contact);
   4:   
   5:      void DeleteContact(Contact contact);
   6:   
   7:      Contact GetContact(int contactId, int portalId);
   8:   
   9:      IQueryable<Contact> GetContacts(int portalId);
  10:   
  11:      IPagedList<Contact> GetContacts(string searchTerm, int portalId, int pageIndex, int pageSize);
  12:   
  13:      void UpdateContact(Contact contact);
  14:  }

The MVC Controller

So now we have everything set up we are ready to create our first MVC Action and View.  Following the MVC convention we will create a class in the Controllers folder called ContactController.  This class must inherit from the DnnController base class found in the DotNetNuke.Web.Mvc project.  This base class inherits from the core MVC Controller base class, but adds extra support for the DNN Module and Portal context.  You can think of this class as the equivalent to PortalModuleBase in WebForms module development.

Figure 3 – The ContactController class

   1:  public class ContactController : DnnController
   2:  {
   3:      private readonly IContactRepository _repository;
   4:   
   5:      public ContactController() : this(ContactRepository.Instance) { }
   6:   
   7:      public ContactController(IContactRepository repository)
   8:      {
   9:          Requires.NotNull(repository);
  10:   
  11:          _repository = repository;
  12:      }
  13:  }

This class has two constructors.  The parameter-less constructor is used by the MVC framework to instantiate the controller, and the second constructor will be used by our Unit Tests.  Use of either constructor will set the private IContactRepository variable.

In the future (DNN NeXt) we will be able to dispense with the parameter-less constructor and allow ASP.NET 5’s Dependency Resolver to inject the appropriate implementation of the interface.  I have used this approach rather than calling DotNetNuke.Instance.<<Method>> in each action method as this will be the pattern used in DNN NeXt.

The Index Action

Next we need to add an action method – the default method is usually called Index by convention.  As we are not really using ASP.NET routing the name is not that important, as DNN actually determines the controller and action to call from the “ControlSrc” property of the Module Control (Contact/Index.mvc).

The Index action is listed in Figure 4.

Figure 4 – The Index Action

   1:  [HttpGet]
   2:  public ActionResult Index()
   3:  {
   4:      var contacts = _repository.GetContacts(PortalSettings.PortalId);
   5:   
   6:      return View(contacts.ToList());
   7:  }

This is a fairly simple MVC Action method.  In the first line we use the HttpGet attribute to indicate that this method should only be called by HTTP “GET” calls. In line 2 we return an ActionResult – the DNN MVC framework captures this result and renders it in the MvcHostControl.  In line 4 we call the GetContacts method of the repository interface to get all the contacts for the portal.  Note, that just like PortalModuleBase the DnnController base class provides access to the PortalSettings object.  Finally in line 6 we return a strongly typed View, passing in our List of contacts.

The Index View

We now turn our attention to the View.  DNN supports all the MVC 5.1 conventions for Views.  Thus, you can provide a _ViewStart.cshtml razor script which will execute for all Views before any other View code, and it supports the use of layout views.  Figure 5 shows this layout.

Figure 5 – MVC View Conventions


Lets look at each of these Razor files.

Figure 6 – _ViewStart.cshtml

   1:  @{
   2:      Layout = "~/DesktopModules/MVC/Dnn/ContactList/Views/Shared/_Layout.cshtml";
   3:  }

The _ViewStart.cshtml file is used to set the Layout property for all the Views.  This allows the module developer to use some common “chrome” for all the Views in the module.

Figure 7 – _Layout.cshtml

   1:  <div class="masterLayout">
   2:      @RenderBody()
   3:  </div>

For this module the shared layout is very simple (being just a wrapper to the required RenderBody() method), but this could be used to register extra css or JavaScript files.

The main view code (Index.cshtml) is shown in Figure 8.

Figure 8 – Index.cshtml

   1:  @inherits DotNetNuke.Web.Mvc.Framework.DnnWebViewPage<IList<Dnn.ContactList.Api.Contact>>
   2:   
   3:  <div>
   4:      @foreach (var contact in Model)
   5:      {
   6:          <div class="contactCard">
   7:              <div>
   8:                  <span>@contact.FirstName</span>
   9:                  <span>@contact.LastName</span>
  10:              </div>
  11:              <div>
  12:                  <span>Email:</span>
  13:                  <span>@contact.Email</span>
  14:              </div>
  15:              <div>
  16:                  <span>Phone:</span>
  17:                  <span>@contact.Phone</span>
  18:              </div>
  19:              <div>
  20:                  <span>Twitter:</span>
  21:                  <span>@contact.Twitter</span>
  22:              </div>
  23:          </div>
  24:      }
  25:  </div>

The first thing to note is Line 1.  DNN Views need to inherit from the DnnWebViewPage class.  This is because we need to modify some of the helper methods, as well as provide support for DNN context (ModuleContext and PortalSettings).  The rest of the code is fairly straightforward Razor script.  We loop over all the contacts in the Model property (which is a List of Contact objects), and render the properties of the contact.  With some simple styling we can see the View output in Figure 9.

Figure 9 – The View output


So thats our first MVC Action/View.  In my next blog post (on MVC modules) I will show how we can add support for other Actions/Views.


For more information

Comments

Jaydeep Bhatt
Great, where is the next Article?
Jaydeep Bhatt Saturday, June 6, 2015 6:48 AM (link)
Jaydeep Bhatt
btw, will "DNN NeXt" support the current WebForm based Modules? OR it will be pure MVC?
Jaydeep Bhatt Saturday, June 6, 2015 6:51 AM (link)
Scippy One
To make working MVC project with DNN 8 CTP4 I had to make some steps in addition to those listed in the articles:
- execute the script Install.sql under src/Dnn.ContactList.Api/Scripts/
- fix the _ViewStart.cshtml adding at first line: @inherits System.Web.WebPages.StartPage
- compile the MVC project in release mode
- install the module package under yourwebsite/Install/Module folder


I want also to thank Charles for these wonderful articles. These are aids that make the community grow in the right direction!...
I hope in the future to find many more!
Scippy One Tuesday, September 15, 2015 11:50 AM (link)
Scippy One
Another little fix to do to run github project is that in Install.sql script the table name is "dnn_Contacts" but in Contact.cs the table name is simply "Contacs", so you need to fix the script before execute it or to fix the class Contact with the right table name.
Regards.
Scippy One Friday, September 18, 2015 8:48 AM (link)
Victor Ogundowo
Nice Article, Charles! Please I have some few questions to ask.
1. If I download the latest DNN 8.0 CTP 4, can I start building the MVC modules inside the WAP, rather than going through the examples you gave in your articles.
2. Can I configure Ninject to Injection my dependences in the constructor of my controller because i used this in all my MVC project.
Victor Ogundowo Friday, September 18, 2015 9:01 AM (link)
Charles Nurse
@Scippy One - thanks for suggesting the fixes needed.

@Victor- (2) because we have to take over the Controller activation then we do not currently support dependency resolution. (1) No - the WAP is not an MVC project as the core is still a WebForms app.

@Jaydeep - We continue to support all other modes of Module development - MVC and the new HTML 5 mode just add extra capabilities.
Charles Nurse Wednesday, September 30, 2015 10:53 AM (link)
Wael Musleh
When inherits from DotNetNuke.Web.Mvc.Framework.DnnWebViewPage the HtmlHelper(@Html) is overrides and all the methods in System.Web.WebPages.Html.HtmlHelper is gone (ex. DropDownList, Raw, CheckBox, ListBox)
Wael Musleh Tuesday, November 17, 2015 10:35 PM (link)
tianxi xi
Im now developing some stuff using new MVC features supported by DNN8. In webforms we can use controls like DnnJsInclude or DnnCssInclude to include client scripts throught Client Resources Management API. Now, it's possible to use the same capabilities in a MVC module?
tianxi xi Wednesday, January 20, 2016 9:19 PM (link)
Scippy One
You can use:

ClientResourceManager.RegisterStyleSheet(Dnn.DnnPage, "~/DesktopModules/MVC/YourModule/YourClass.css");


ClientResourceManager.RegisterScript(Dnn.DnnPage, "~/DesktopModules/MVC/YourModule/YourJavascript.js");
Scippy One Tuesday, January 26, 2016 11:48 AM (link)
sushi sushi
Hello, I am new to dotnetnuke. I have many tables with many columns, how can I generate the Model / view / controller classes to use? I know I can copy the Item.cs file and change all the columns to my table's column, but that is really a huge job and I think it will save a lot of time if we have a way to generate all the model classes.
sushi sushi Saturday, May 6, 2017 1:50 PM (link)
Michael Durthaler
Where is there a written article series on using the C# DNN8 DAL2 MVC template? I can't find one anywhere and the frustration experienced thus far is very intense and agonizing to be frank.

The videos I can find show *nothing* and it's not like I can't do MVC. I use it at work and have rewritten some half a dozen classic ASP sites for my employer using some Ext JavaScript but mostly jQuery and Bootstrap.

Finding full examples on DNN ... good luck.

This article does not show *what file* to add the ModuleAction attribute to in a template nor how to set up a file in a template to work with DNN.

It also says you can't add a Module Action attribute to a Controller but in Chris Hammond's template, this is where the Module Action attribute *is*.

The problem is the pencil icon isn't showing up.

Here are the steps taken:

1. Set up VS 2015 Professional
2. Set up IIS
3. I use the hosts file to set up my own custom URL so did not use dnndev.me -- but I like this idea that it already does the loop back for me.
4. SQL Server is set up.
5. Site works ...

Created a module project for the DAL2 MVC and it's under .../DesktopModules/MVC/ where it should be.

Built the module, dropped it on a page.

Was able to make sure debugging works from the project solution. It does.

Added some text to a Setting file for a sanity check. It will show up.

So ... where's the pencil icon for this critter? Also, where in the *heck* (sorry for the frustration) is there a simple written series on how to develop a DAL2 module from this template?

Thanks,

Mike
Michael Durthaler Sunday, May 28, 2017 11:19 PM (link)
jigar tanna
Hello,
Thanks for the excellent explanation,

Can you please tell me or share the Demo/video
How can i work with SQL table with DNN using MVC template?
How to connect with Sql server in DNN mvc template?
jigar tanna Friday, December 8, 2017 8:42 AM (link)

Comment Form

Only registered users may post comments.

NewsArchives


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Daniels (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out