T4MVC not generating some Actions for one Controller - t4mvc

I have a situation where T4MVC is generating everything properly (meaning intellisense shows all areas/controllers/actions and everything compiles), but when I run the code, I get a T4MVC was called incorrectly runtime error.
I've investigated the generated files and discovered that for one controller in my project, only actions in the base class are getting the overridden stub actions generated. For other controllers, all actions are being generated. They all have the same set up, described below.
I have a BaseController class that has some shared code (and inherits from Controller). In the Controllers directory (root of project) I have a number of controllers, all which inherit from BaseController.
I then have several Areas. In each Area, I have the same controllers, each inheriting from the controller of the same name in the root Controllers directory.
Running T4MVC (version 2.6.54), everything works fine except for one controller. The odd thing is that intellisense works for the controller, but chokes when the actual action is referenced (in an ActionLink() call).
I manually added one action in particular into the generated code and there was no error.
So my question is, what would cause T4MVC to not generate all code for a controller? The missing actions are all public virtual ActionResult and the actions themselves work fine. The problem controller has the same issue in all Areas.
Some abbreviated code.
/Controllers/BaseController.cs
namespace MyProject.Controllers
{
public abstract partial class BaseController : Controller
{
protected ISession session;
public BaseController()
{
}
// other shared methods/actions
}
}
/Controllers/ActivitiesController.cs (this is the problem controller)
namespace MyProject.Controllers
{
public partial class ActivitiesController : BaseController
{
// for resolving concurrency exceptions
private Activity userValues;
private Activity databaseValues;
public ActivitiesController() : base()
{
ViewBag.ControllerName = "Activities";
}
// this action is causing the problem used like
<li>#Html.ActionLink("Activities", MVC.Areas.Module1.Activities.Index())</li> in a view
public virtual ActionResult Index()
{
return View();
}
}
}
/Areas/Module1/Controllers/ActivitiesController.cs. This is the whole class
namespace MyProject.Areas.Module1.Controllers
{
public partial class ActivitiesController : MyProject.Controllers.ActivitiesController
{
public ActivitiesController() : base()
{
base.currentModule = Modules.Module1;
}
}
}

In case anyone else comes across this I had a similar issue and resulting run-time error message but in a bit different scenario. It was in the RedirectToAction statement at end of a ActionResult method:
RedirectToAction(Edit(id));
The error went away after correcting it to:
RedirectToAction(MVC.[action name].Edit(id));
The error message isn't very intuitive and the suggestion to re-run the custom tool doesn't really help.

Did you make sure to re-run T4MVC to generate based on the latest (Right click .tt file / run custom tool)?
If that's not the problem, I may need to look at a sample app that has the problem to see what's going on.

Related

What is the recommended way to preserve custom code in scaffold generated Controller and View Code?

I am using MVC3 with EF5. I like the way I get scaffold generated Controllers and Views. This produces a nice workflow to create an application quickly and consistently. Of course the initial idea behind Scaffolding was to create a 80% quick start, and obviously the Controllers and Views get quickly customised. However are there any recommended practices for retaining custom code while still being able to rerun the scaffolding. The nearest I can think of is having external method calls from the controller actions etc.. I guess I would then need to incorporate these into the T4 templates??? Perhaps Dependency Injection has a role here? I have seen it used in the Domain Layer for extra service methods.
Perhaps I am hoping for too much !!!
Many thanks for any ideas.
Using auto-generated code for controllers, just make sure the code generated creates partial classes.
As for views, it much more difficult (some times impossible) to change a view and have it re-generated without losing what you needed after you changed it.
Updated
You could have your code generator create files like:
Controllers/ClientController.Auto.cs (Auto added to denote auto generated)
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
namespace SomeCompany.SomeProjectName.Controllers
{
public partial class ClientController
{
public SomeAutoGeneratedMethod()
{
}
public SomeAutoGeneratedProperty { get; set; }
}
}
Controllers/ClientController.cs
using System;
namespace SomeCompany.SomeProjectName.Controllers
{
public partial class ClientController
{
public SomeProgrammerWrittenMethod()
{
}
public SomeProgrammerWrittenProperty { get; set; }
}
}

Can't get log4net working in MVC3 sub-classed controller

I have an MVC3 application that I'd like to get log4net working in.
I got the code I'm using from this site
I can get the logging to work if I add this code to an Action method.
public ActionResult Index() {
log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());
log.Info("Here I am in Index.");
return View();
}
I'd like to enable logging in all my controllers, so I added the following class to my project,
public class LoggingController :Controller {
protected log4net.ILog Log;
public LoggingController () {
Log = log4net.LogManager.GetLogger(GetType());
}
}
and I'm having my Home controller inherit from this class, LoggingController.
I've put a break point on my LoggingController's constructor and determined the constructor is being called, however my logging isn't working when done this way.
My question then is:
Why isn't this working?
OR
Is there a better way of accomplishing what I'm trying to do here?
Thanks in advance.
Why isn't this working?
Because the type argument you pass to the GetLogger method must match that of the containing type. You are passing HomeController (by using GetType()) instead of LoggingController which is where the variable is declared. Try like this:
public LoggingController () {
Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
}

MEFContrib.MVC3: Exporting Controllers with Base Classes

I have opened up a question on CodePlex but have not received any responses at all.
Basically, I have a base controller that all of my controllers inherit from. When I create a new MVC3 project, put my controllers in another assembly, and add MEFContrib.MVC3 to the project, everything works great. When I make any of the controllers inherit from my base class, they can no longer be found.
I am not familiar enough with MEFContrib to know what exactly is breaking, but I have tried to decorate my controllers with ExportAttributes and that has not worked, either.
All of this is a different assembly than the main MVC project:
public class MyBaseController : Controller
{
...
}
// This controller cannot be found.
public class HomeController : MyBaseController
{
public ActionResult Index ()
{
// Do Stuff
return View ();
}
}
// This controller can be found.
public class HomeController : Controller
{
// yada, yada, yada...
}
Edit:
counsellorben was exactly right. I had dependencies that were not properly marked for export and so the controllers could not be properly composed. I stepped through each of my dependencies, stepping through their own dependencies, and found the few I missed.
The most likely issue is that there is a problem with a dependency in your MyController class. This will cause a problem with any controller inheriting from MyController.
Please see this answer for some sample code you can use to try and diagnose where your problem lies.
I think you need to decorate with the InheritedExport attribute.

MVC3 Routing Issues - How to re-use a View for all Controller Methods?

I'm trying to implement a common controller in MVC3 to return various JSON feeds, example -
public class AjaxController : Controller
{
public ActionResult Feed1()
{
ViewBag.Json = LogicFacade.GetFeed1Json();
return View();
}
public ActionResult Feed2()
{
ViewBag.Json = LogicFacade.GetFeed2Json();
return View();
}
}
This class has 30+ methods in it, the problem is this requires implementing an IDENTICAL View for each of the Controller's methods (sigh) that writes out ViewBag.Json.
I'm assuming this is a routing issue but I'm struggling with that. The following didn't work -
Tried setting ViewBag.Json then using RedirectToAction() but that seems to reset ViewBag.Json.
Note JsonResult is not appropriate for my needs, I'm using a different JSON serialiser.
So the objective here is to maintain one View file but keep this class with seperate methods that are called by routing, and not a crappy switch statement implementation.
Any help appreciated.
Use the same view and just specify the name. You can store in the controller's view folder, if only used by one controller, or in the Shared view folder if used by more than one.
return View("SharedJsonView");
Another, perhaps better, solution would be to create your own result -- maybe deriving from JsonResult, maybe directly from ActionResult -- that creates the JSON response that you need. Look at the source code for JsonResult on http://www.codeplex.com/aspnet for ideas on how to do it.

Error "A namespace does not directly contain members such as fields or methods"

I'm trying to build my C# project and I'm getting the error message "A namespace does not directly contain members such as fields or methods". It is flagging the first character (the less than symbol) of the app.config file.
I've checked all of my files for places where there are variables or functions directly inside of a namespace--found nothing. The app.config looks fine.
Google is failing me and I'm pulling my hair out. What could be causing this error?
Figures! As soon as I finally break down and ask the question that I find the answer...
The app.config file properties section (somehow) listed the Build Action of "Compile" when it should be set to "None".
How in the world did it get changed? I know I didn't change it. Grrr...
Oh well, at least it's building now. Hopefully someone else will benefit from my hairloss.
I managed to reproduce the error.
Check the properties for the app.config file. The Build Action should be None, not Compile.
This error occurs when you attempt to add a field or member directly into a namespace. Given it's pointing to app.config it's likely that VS is in a bad state. Try closing and reopening Visual Studio and see if the error goes away.
Failing that try rebuilding and posting the results from the build output window to your question.
I solved this way: right click on .axml file -> Build Action ->AndroidResource
(xamarin studio)
I had the same error. Checked if the app.config was set to none, no problems there. After 30 minutes of checking and rechecking, I restarted VS and that did the thing. It usually solves 90% of the unlogical errors. Sighs.
I was having a similar problem with the code behind in my website.
The issue turned out to be an extra closing bracket that caused my class to end right after page_load(). Always check for silly syntax errors like this one.
I was facing this same issue with XML file. This was due to .net compiler tried to compile this xml which has been used only for DATA purpose hence no need of compilation.
Fix : Go to property of this file and change the Build Action to content from compile.
Thanks
In my case i was by mistake putting a new function outside the controller class.
This was my code in ASP.NET MVC that was giving this error.
public class HomeController : Controller
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
}
[HttpPost]
public string Insert(string name, string age, string standard, string percent, string address, string status)
{
//some code
return "value";
}
}
It should be like:
public class HomeController : Controller
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public string Insert(string name, string age, string standard, string percent, string address, string status)
{
//some code
return "value";
}
}
}

Resources