Ayalas
Ayalas

Reputation: 15

How to Post/Get and not wait for the response (Async like Ajax) in asp net

I'm working with c# mvc 5 and I have a url which writes a log. I call it in ajax in all my pages via javascript:

$.ajax({ url: log?page=index&userid=15, async: true });

Now I'm willing to log more critical data, so, for safety matters I need to remove this javascript from my pages, and instead, put it in every controller and every action of my projects.

There is a way to do this asyn in asp net mvc 5? What I want is something like this:

public ActionResult Index()
{
    // I want a method that makes a post/get to some url, but don't block
    // the rest of the code. I don't need any return from the post
    // It would be nice to be a Post, but a Get would do the trick
    PostOrGetAsync("log?page=index&userid=15");
    return view();
}

Thank you in advance!

Upvotes: 0

Views: 2286

Answers (1)

Erik Philips
Erik Philips

Reputation: 54638

There is a way to do this async in asp net mvc 5? What I want is something like this:

Yes. However, your url in ajax log?page=index&userid=15 does not appear to be a remote server so you can call it directly.

public async ActionResult Index()
{
  // I want a method that makes a post/get to some url, but don't block
  // the rest of the code. I don't need any return from the post
  // It would be nice to be a Post, but a Get would do the trick
  var controller = new LogController();
  await controller.Log("index", 15);
  return view();
}

This really isn't maintainable. To make it global requires a little bit of work. You can use an ActionFilter to globally log all calls.

public class LogActionFilterAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    Log("OnActionExecuting", filterContext.RouteData);       
  }

  public override void OnActionExecuted(ActionExecutedContext filterContext)
  {
    Log("OnActionExecuted", filterContext.RouteData);       
  }

  public override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    Log("OnResultExecuting", filterContext.RouteData);       
  }

  public override void OnResultExecuted(ResultExecutedContext filterContext)
  {
    Log("OnResultExecuted", filterContext.RouteData);       
  }


  private void Log(string methodName, RouteData routeData)
  {
    var controllerName = routeData.Values["controller"];
    var actionName = routeData.Values["action"];
    var message = String.Format("{0} controller:{1} action:{2}", 
      methodName, 
      controllerName, 
      actionName);

    Debug.WriteLine(message, "Action Filter Log");
  }
}

You can either apply the Log to specific actions/controllers:

[LogActionFilter()]
public ActionResult Index()
{
  return view();
}       

or all controllers:

protected void Application_Start()
{
  // Register global filter
  GlobalFilters.Filters.Add(new MyActionFilterAttribute());
  RegisterGlobalFilters(GlobalFilters.Filters);
}

However, does not currently support async action filters, but I don't think you need it anyway.

I need some information that is inside the method. Like, when the user is creating a new registry.

[LogActionFilter()]
public ActionResult Index()
{
  SomeSharedLogic();

  return view();
}       

Extension Method

public static ControllerExtensions()
{
  public static void SomeSharedLogic(this ControllerBase controller)
  {
    controller.TempData["ShareLogicValue"] = "WhateveR";
  }
}

Update the log method

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
  var sharedLogic = filterContext.Controller.TempData["ShareLogicValue"]
    as String;

  var logName = "OnActionExecuted";

  if (sharedLogic != null)
  {
    logName += ":" + sharedLogic;
  }

  Log(logName, filterContext.RouteData);       
}

Upvotes: 1

Related Questions