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);
}
Related
im using laravel 5.
I need to call a controller function but this should be done in another controller.
I dont know how to do this
public function examplefunction(){
//stuff
}
And i have a Route for this function, so at
public function otherfunctioninothercontroller(){
// I need examplefunction here
}
how Can i do this?
1) First way
use App\Http\Controllers\OtherController;
class TestController extends Controller
{
public function index()
{
//Calling a method that is from the OtherController
$result = (new OtherController)->method();
}
}
2) Second way
app('App\Http\Controllers\OtherController')->method();
Both way you can get another controller function.
If they are not in the same folder, place use namespace\to\ExampleClass; on top of your file, then you are able to instantiate your controller.
You can simply instantiate the controller and call the desired method as follows
FirstController.php:
namespace App\Http\Controllers;
class FirstController extends Controller {
public function examplefunction() {
// TODO: implement functionality
}
}
SecondController.php:
namespace App\Http\Controllers;
class SecondController extends Controller {
public function test() {
$object = new FirstController();
$object->examplefunction();
}
}
Now, after i've answered the question, i would like to add the following comment:
Controllers are classes, all rules that applies to normal classes can be applied to them
However, instantiating a controller directly inside another controller to call a desired method signifies a problem in your design for the following 2 reasons:
A controller cannot obtain an instance of another controller directly
Controller should contain as little business logic as possible, and if possible none
The closest possible solution to what you want (WITHOUT BREAKING MVC) is to make an HTTP request to the route that points to the desired method (using cURL, for example) and read the response as the returned data
But this still doesn't make much sense in this scenario because after all you're making an HTTP request from a method in a controller in your project on your server to a method in a controller in your project on your server, seems like unnecessary overhead, right ?
As i said earlier, a controller should contain as little business logic as possible because the logic should stay inside specialized classes (commonly known as Service Classes), and when a processing is requested the controller simply delegates the job of processing to the appropriate service class which does the processing and returns the results to the controller which in turn sends it back as a response
Now imagine if you've the following scenario:
We've got an application that consists of 3 functionalities:
A user can register an account from web application
There's a mobile application that talks to an API to register a user
There's an admin panel, which he can use to add new user
Obviously you need to create 3 controllers, but those controllers contains repeated logic, would you copy/paste the code everywhere ?
Why not encapsulate this logic inside a service class and call it from the controller when needed ?
Let's say I have Controller1 and Controller2. I want to call a function of Controller1 from inside a function placed in Controller2.
// Controller1.php
class Controller1 {
public static function f1()
{
}
}
And on the other controller:
// Controller2.php
use App\Http\Controllers\Controller1;
class Controller2 {
public function f2()
{
return Controller1::f1();
}
}
Points to be noted:
f1() is declared static
A call to a controller from inside another controller is a bad idea. There is no sense of meaning of controllers then. You should just redirect to web.php to save safe whole architecture like this:
class MyController {
public function aSwitchCaseFunction(Request $requestPrm){
...
//getting path string from request here
...
switch($myCase){
case CASE_1:
return redirect()->route('/a/route/path');
....
}
}
}
This is a beginner question, but I searched for an hour and couldn't find an answer.
I am trying to write a simple data query which I included in my HomeController
<?php
class HomeController extends BaseController {
public function showWelcome()
{
return View::make('hello');
}
}
$programs=DB::table('node')->where('type', 'Programs')->get();
$programs is undefined so I am guessing that my query didn't work but I have no idea how to debug it. I tried installing firebug and phpbug and chromphp tools but they don't seem to show anything. My apache log doesn't show anything either. Am I missing something? How do I debug this?
You can't use an expression outside of a method when using a class, instead you need to put it inside a method like:
class HomeController extends BaseController {
public function getPrograms()
{
$programs = DB::table('node')->where('type', 'Programs')->get();
// pass the $programs to the programs view for showing it
return View::make('programs')->with('programs', $programs);
}
}
So, for example, if you have a route like this:
Route::get('/programs', 'HomeController#getPrograms');
Then you may use an URL like: example.com/programs to invoke the getPrograms method in the class HomeController.
Probably this answer doesn't help much but I think you should learn the basics (PHP Manual) first so read books and articles online and check the Laravel website to read the documentation.
You can pass the result of that query to the view like so:
class HomeController extends BaseController {
public function showWelcome()
{
$programs = DB::table('node')->where('type', 'Programs')->get();
return View::make('hello', array('programs' => $programs));
}
}
And in your view you will have access to the $programs variable.
I don't know If i'm missing the point, but can't you use the "dd($programs)" to check what is or not is inside the variable?
I have a Controller with syntax like this:
public class CrudController<TEntity> : Controller
Now if I need a CrudController for Entity User, I just need to extend the CrudController like this
UserCrudController : CrudController<User>
Its working just fine. But, the thing is, the UserCrudController is simply empty. Also, there are some other CrudControllers which are empty too.
Now, I am looking for a way to avoid writing the empty crud controllers. I simply want to create Instances of CrudController with appropriate generic argument. Perhaps by a strict naming convention as described bellow.
The URL will be like: #Html.ActionLink("Create", "UserCrud")
When the URL will be received, it will try to locate the controller named UserCrud (The default thing)
If it fails to locate UserCrud, Crud<User> will be created.
Now, I can do the things I want to do. But exactly where do I do these? Where is the url parsed in mvc?
With help of Craig Stuntz's comment on the question and this question and its accepted answer, I have solved my problem.
I have implemented a custom CotrollerFactory
public class CrudControllerFactory : DefaultControllerFactory {
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) {
Type controllerType = base.GetControllerType(requestContext, controllerName);
if(controllerType == null) {
int indexOfEntityEnd = controllerName.LastIndexOf("Crud");
if(indexOfEntityEnd >= 0) {
string entityName = controllerName.Substring(0, controllerName.Length - indexOfEntityEnd - 1);
// Get type of the CrudController and set to controller tye
}
}
return controllerType;
}
}
And then in Application_Start(), I added this line:
ControllerBuilder.Current.SetControllerFactory(typeof(CrudControllerFactory));
İn my MVC3 project, there is plenty of TempData[] that I am using for passing datas between actions. And it works totaly perfect when I use Chrome. But in IE I can't get values of TempData[] items. if anyone knows whats the problem and how can I solve it?`
public class SomeController : Controller
{
public ActionResult SomeAction()
{
TempData["id"] = "someData";
return View();
}
}
public class AnotherController : Controller
{
public ActionResult AnotherAction()
{
string data = Convert.ToString(TempData["id"]);
return View();
}
}
`
You should never return a view from a controller action that stores something into TempData. You should immediately redirect to the controller action that is supposed to use it:
public class SomeController : Controller
{
public ActionResult SomeAction()
{
TempData["id"] = "someData";
return Redirect("AnotherAction", "Another");
}
}
public class AnotherController : Controller
{
public ActionResult AnotherAction()
{
string data = Convert.ToString(TempData["id"]);
return View();
}
}
The reason for this is that TempData survives only for a single additional request. So for example if inside the view you are sending an AJAX request to some controller action (no matter which) and then have a link in this view pointing to the target action, when the user is redirected to this target action TempData will no longer exist since it was lost during the AJAX request done previously.
If you need to store data for longer than a single redirect you could use Session.
If you need to store data for longer than a single redirect you should use Keep or Peek methods.
string data = TempData["id"].;
TempData.Keep("id");
or simply use,
string data = TempData.Peek("id").ToString();
Peek function helps to read as well as advice MVC to maintain “TempData” for the subsequent request.
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.