This project is read-only.

Turning a fully functional MVC project into an Orchard Module/Widget. HOW?

Topics: Troubleshooting, Writing modules
Jun 24, 2011 at 2:52 PM

Okay, I have been at this for days and I didn't even know where to start, so I decided to turn to these forums to see if this has been done before (either no one has or it's incredibly easy because I have found nothing on the internet about it)

I have a working MVC project that I just finished writing. It uses multiple controllers, views, partial views, etc. It also uses a controller factory (Ninject) and I think that may be one of my problems. The program accesses and makes changes a database of my own (SQL), that it connects to through the appropriate connection string stored in Web.config.

Now I am faced with the task of making it into a module or widget in Orchard. I have been scouring the internet and I haven't found anything about doing what I am trying to do. I've studied the Hello World tutorial on the Orchard site for hours trying to figure out what I might be missing. 

I tried making module.txt and Routes.cs files, with no luck. I've also tried adding the extra constructor and localization lines I found in the HelloWorld source download (that aren't actually shown in the online tutorial...). Every time I change something I just get a different random error. Often they are things like ADOExceptions somewhere in Orchards code, so I don't even know what I've done wrong. 

Does anyone have any insight on the task of converting an MVC project into a module? It would be much appreciated. And I apologize if I have missed any threads or guides on this that will solve all my problems.


Thanks in advance

Jun 24, 2011 at 4:23 PM

I think you'll have to factor out Ninject - Orchard uses Autofac for dependency injection which covers controllers as well, so you'll likely get conflicts there.

Otherwise it should be straightforward - if you haven't used MVC areas yourself, then your whole project should be able to just sit in Orchard as an MVC area (which is all that Orchard modules are behind the scenes).

ADOExceptions can occur for a variety of reasons, sometimes it can be when you're passing IQueryables down into the view, but the transaction scope has expired by the end of your Action. So you need to .ToList() any data you're sending into your view.

Otherwise if you can be more specific providing an exception detail and your code that's causing it, someone can probably help you further :)

Jun 24, 2011 at 5:02 PM
Edited Jun 24, 2011 at 8:06 PM

Well thank you for the quick response, randompete. I cheated out of using Ninject by hard coding my repository declaration into the controller (for now at least). I must apologize as I'm still pretty new to MVC as well, so it's possible I'm doing weird things all over.

Anyway, with that hard coded and the use of a breakpoint or two, I have learned that it actually does run through the proper action in my controller, I hadn't thought it was getting that far. When it gets to my return View(viewModel); statement, it then jumps through a couple Orchard files and gets stuck on one called Repository.cs, giving me an error here:


public virtual T Get(int id) {
            return Session.Get<T>(id);


(on the return statement)

It's an ADOException, and here is the associated description I guess:


While preparing SELECT contentite0_.Id as Id226_0_, contentite0_.Data as Data226_0_, contentite0_.ContentType_id as 
ContentT3_226_0_ FROM Orchard_Framework_ContentItemRecord contentite0_ WHERE contentite0_.Id=@p0 an error occurred

Judging by what you've told me, I suppose it may be my viewmodel that's tripping it up. Here it is:


public class ListViewModel
		/* List of columns with information to be shown and additional necessary information */
		public List<DBColumns> Columns { get; set; }
		/* Contains all of the firm names, used in the DDL to filter by firm */
		public List<SelectListItem> FirmDropDown { get; set; }
		/* Used for displaying the firm name at the top of the ConfigTables partial view */
		public string FirmName { get; set; }
		/* Used for transmitting the current DDL selected firm to the controller */
		public string FirmID { get; set; }

The only part being used at this point is FirmDropDown. I'm not entirely sure if it's an IQueryable that can be fixed the way you said (is it not already a list?)

Jun 24, 2011 at 5:43 PM

I think it's exactly what I was saying; you need to enumerate your data *before* passing it into the view, but can you post your action code so I can see how you're creating the ListViewModel?

Jun 24, 2011 at 6:11 PM

Sure thing.

public ActionResult List(int? firmID)
			// view model containing only the firm drop down information
			// table data will only be rendered once user requests it
			var viewModel = new ListViewModel
				FirmDropDown = (from cor in repository.cFM
						orderby cor.CN
						select new SelectListItem
							Text = cor.CN,
							Value = cor.LFirmId.ToString()
				FirmID = firmID.ToString()
			return View(viewModel);

Jun 24, 2011 at 6:30 PM

Well, that should be fine - I take it that debugging you can see the correct data in the ViewModel?

What's in your View code?

Jun 24, 2011 at 6:36 PM
Edited Jun 24, 2011 at 7:17 PM

Yes, the FirmDropDown is populated properly, the rest is null as it's not used at first. Here's my view, it's just a drop down list that updates a partial view when changed:


@model ConfigMod.Models.ListViewModel

    ViewBag.Title = "Sample";

<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.blockUI.js" type="text/javascript"></script>

@using (Ajax.BeginForm("ConfigTable", null, new AjaxOptions
    UpdateTargetId = "result"
}, new { id = "ajaxForm" }))
<div class="mainBar" >
	    <b>Firm: &nbsp</b>
	    @Html.DropDownListFor(x => x.FirmID, Model.FirmDropDown, "--Select a Firm--", new { onchange = "fnSubmitOnSelect()" })
        <b>What do you want to do? &nbsp</b>
        @Html.TextBox("Application", "This will be a dropdown eventually...")

<script type="text/javascript" >
    $(document).ready(function () {


    function fnSubmitOnSelect() {

     function BlockUI() {
         $.blockUI({ message: '<h1>Just a moment...<br/><img src="/Content/images/ajax-loader.gif" /></h1>',
             overlayCSS: {
                 backgroundColor: '#000',
                 opacity: 0.3
             fadeIn: 500



<div id="result">




I replaced the entire view with this:


<h2>@T("Hello World!")</h2>

and got the same error


With the view still nothing but Hello World, I also replaced the return statement in my action to read just  

return View();
thus not even using the view model, and I still get the same error...  ;___;

Jun 24, 2011 at 7:39 PM

If you do your own database access, you need to opt out of Orchard's ambient transaction. This is done by surrouding your data access code with a using (new TransactionScope(TransactionScopeOption.Suppress).

Jun 24, 2011 at 7:55 PM
Edited Jun 24, 2011 at 7:58 PM

Oh wowee. I don't understand it, but it worked! Thanks bertlandleroy and randompete for all the help :)

Er.. new issue now though...

It doesn't seem to like JavaScript very much, giving me things like "Microsoft JScript runtime error: '$' is undefined" and "Microsoft JScript runtime error: 'Sys' is undefined"

Am I doing something else wrong? Or is this a known issue? Is JavaScript/Ajax not compatible with Orchard??  D:

Also this: "Microsoft JScript runtime error: The value of the property '$' is null or undefined, not a Function object"

Jun 24, 2011 at 8:02 PM

I can explain: Orchard has an ambient transaction around its unit of work, so that you don't have to worry about transactions most of the time. Just modify your objects and unless you need to rollback the transaction you don't need to worry about it. In other words, we do not require code for the common case (everything is going well), but only when something went wrong (abort everything! revert what you just did!). Of course this breaks down if you need to write code that should not be included in the Orchard transaction, such as custom data access code to another database. Hence the suppression of the ambient scope.

JavaScript is perfectly compatible with Orchard :). It's just that you are in a collaborative, modular architecture now so everyone needs to play nice with common resources. Scripts are common resources: more than one module may require jQuery for example and you don't want to include it twice. The API that you need to learn about are Script.Require and Script.Include. Specifically, you'll need to Script.Require("jQuery") instead of injecting a script tag.

Jun 24, 2011 at 9:20 PM

Okay, sorry to be a fish, but I tried adding @Script.Require("jQuery") to the top of my view, and now it gives me "The name 'Script' does not exist in the current context"

I found a few threads on here addressing that, but I was still unable to solve my problem. I tried not using debug mode, and it still gave me that horrible yellow screen. I also tried merging as well as totally replacing my web.config with one from a different module, since mine was copied in from the pre-orchard MVC project. Still nothing. I can't remember at this point if I actually used codegen in the console to start this module, so I may be missing a reference a dependency or two.

Jun 24, 2011 at 9:31 PM

You probably need the right references and/or Web.config in your project. Did you use the codegen feature to make the new project, or are you trying to convert an existing one?

Jun 24, 2011 at 9:33 PM

Converting an existing one. Would it be better at this point to move my project out, codegen one of the same name, and copy the contents back in excluding web.config? Possibly excluding other things but I don't know what?

Jun 24, 2011 at 9:48 PM

It's mainly the Web.config and references; codegen an empty module and see what's in there. You'll also see things like each of the resource-type folders have a specific Web.config allowing static files to be served, things like that. The Web.config is very different to a usual MVC project I think.

Jun 27, 2011 at 4:08 PM

Okay I'm assuming I've fixed the web.config issue because I no longer get the error about Script not existing. However, I am now back to getting "The value of the property '$' is null or undefined, not a Function object" etc.

I have tried adding 



And I still receive the errors. The @Script. ... lines only seem to add "Orchard.UI.Resources.RequireSettings;" to the top of my view's output (like in the browser)... and when I look in the source, the references are not added anywhere. And for all three of the above lines I've tried, it always outputs the same thing. Has anyone seen this before?

Oh and I also tried commenting my original <script> tags that included the necessary script files.


Jun 27, 2011 at 4:41 PM

@ is the Razor syntax for "print". You shouldn't use it for Script.Require etc. - you're not printing anything, you're making a function call. So wrap all those calls in an @{ ... } code block.

Jun 28, 2011 at 6:26 AM

I hope this explains it a bit better. What randompete says is to write it like so.

    Script.Include("your_js_file.js");// this file is under YourModule/Scripts/your_js_file.js

Jun 29, 2011 at 2:51 PM

I got it working, and am on my way to new errors and issues  xD

Thanks for the help guys!