Performing Registration Operations in MVC.NET

I am trying to develop a better method for logging in an application that I am currently developing.

right now, I have a log table that stores username, timestamp, action, controller, and message. when a controller is created, it receives IoC information through Castle Windsor.

for example, my Sites controller is created like this:

    private ISitesRepository siteRepository;
    private ILogWriter logWriter;

    public SiteController(ISitesRepository siteRepository, ILogWriter logWriter)
    {
        this.siteRepository = siteRepository;
        this.logWriter = logWriter;
    }

      

and the write log has a function that creates and inserts a record into the log (WriteToLog). in the controller "Sites" "Edit" and "Create Actions" it calls the WriteToLog function.

this works and gets the job done, but my question is, do I really need to configure each controller in this way, going through the ILogWriter interface / repository? I felt like I could customize the LogController, and I just have a "heavy lift" to write to my logs.

this way I wouldn't have to mess with IoC stuff in every other controller. is it possible to perform an action on another controller (eg LogController-> WriteLog)? I'm not sure how this could be done without redirection ...

+2


source to share


2 answers


Ok, after a big head scratch, I think I have found an acceptable solution.

I have implemented my registration action as a custom action filter like so:

public class LogAction : ActionFilterAttribute, IActionFilter
{
    public LogLevel loglevel;
    public string message;


    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();

        logWriter.WriteToLog(
          filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, 
          filterContext.ActionDescriptor.ActionName,
          loglevel,
          filterContext.HttpContext.Timestamp,
          filterContext.HttpContext.User.Identity.Name.ToString(),
          message + "(id=" + filterContext.RouteData.Values["id"] + ")");
    }

}

      

but I ran into a wall trying to get IoC to work in a custom attribute filter. cleaning up stackoverflow and google searches, I found it tricky to do, with talk about using different wrappers, action invokers, etc. that all seemed more complicated than I really wanted to deal with.

while trying to learn more about IoC (I'm still very new to this) I found this article which really helped me in the right direction. I added my private AppServiceFactory class using WindsorControllerFactory and it worked like a charm.

As I said, I'm very familiar with MVC and this IoC stuff, so I'm not sure if this is the ideal way to handle things, but it seems simple and works so far. I would welcome any comments or criticisms on handling this method.



UPDATE Figured out another way to do it - created a function in my WebUI project as such:

public static class Loggers
{
    public static void WriteLog(ControllerContext controllerContext, LogLevel logLevel, string message)
    {
        ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
        logWriter.WriteToLog(
            controllerContext.RouteData.Values["controller"].ToString(),
            controllerContext.RouteData.Values["action"].ToString(),
            logLevel,
            controllerContext.HttpContext.Timestamp,
            controllerContext.HttpContext.User.Identity.Name.ToString(),
            message);
    }
}

      

now wherever I want to record something, I can call

            Loggers.WriteLog(
            this.ControllerContext,
            LogLevel.Membership,
            "Removed role '" + role + "'" + " from user " + _userService.Get(id).UserName );

      

to write the entry to the log. this gives me a lot of flexibility in my "message" content and solves the problem of including the registration in the global.asax file, which would be difficult if not impossible using attribute filters. I'll leave the rest as it might be useful to someone else, but I think that's how I'll continue.

as usual it is usually easier in MVC than in the original, I think they will :)

+1


source


Could you walk through the abstract class? Does this abstract class have a static property referencing you journalist?

something like that



public abstract class BaseController
{
    public static ILogWriter Logwriter{get;set;}
    public static BaseController
    {
        Logwriter = YourFactory.GetLogwriter();
    }
}

public class YourController:BaseController
{
    public YourController(ISitesRepository siteRepository)
    {
    }
}

      

+1


source







All Articles