Ivan-Mark Debono
Ivan-Mark Debono

Reputation: 16290

Web Api and session variable?

I have a web api controller and I need to audit the user that did the changes. Currently I do the following:

public class CustomerController : ApiController
{
    private readonly ICustomerService customerService;
    private bool userSet = false;

    public CustomerController(ICustomerService customerService)
    {
        this.customerService = customerService;
    }

    [NonAction]
    private SetUser(string userId)
    {
        if (userSet)
            return;

        //Get user from repository... here just for the example
        var User = GetUser(userId);

        customerService.SetUser(user);
        userSet = true;
    }

    public Customer GetCustomer()
    {
        CookieHeaderValue cookie = Request.Headers.GetCookies("userId").FirstOrDefault();
        SetUser(cookie["userId"].Value);

        //code...
    }

    public int PostCustomer(Customer customer)
    {
        CookieHeaderValue cookie = Request.Headers.GetCookies("userId").FirstOrDefault();
        SetUser(cookie["userId"].Value);

        //code...
    }

    public void PutCustomer(int id, Customer customer)
    {
        CookieHeaderValue cookie = Request.Headers.GetCookies("userId").FirstOrDefault();
        SetUser(cookie["userId"].Value);

        //code..
    }

    public void DeleteCustomer(int id)
    {
        CookieHeaderValue cookie = Request.Headers.GetCookies("userId").FirstOrDefault();
        SetUser(cookie["userId"].Value);

        //code...
    }
}

I am getting the userid that is in the request, and I set the user in the service. However, I have many more controllers and these have many more actions.

Is this the way to do it or is there any alternative that I can set the userId for the 'session' (although not using the standard Session in Web API)?

Upvotes: 1

Views: 1372

Answers (3)

Arnold
Arnold

Reputation: 98

you can inherit DelegatingHandler , for example:

public class MessageHandler1 : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("Process request");
        // Call the inner handler.
        var response = await base.SendAsync(request, cancellationToken);
        Debug.WriteLine("Process response");
        return response;
    }
}

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new MessageHandler1());


        // Other code not shown...
    }
}

If you want to see in more detail,see here

enter link description here

Upvotes: 1

Trevor Pilley
Trevor Pilley

Reputation: 16393

You can make a base controller:

public abstract AuditableActionController : ApiController
{
    private readonly ICustomerService customerService;

    protected AuditableActionController(ICustomerService customerService)
    {
        this.customerService = customerService;
    }

    protected ICustomerService CustomerService { get { return this.customerService; } }

    protected override void Initialize(HttpControllerContext controllerContext)
    {
        SetUser(cookie["userId"].Value);

        // Make sure you call the base method after!
        base.Initialize(controllerContext);
    }

    private void SetUser(string userId) { ... }
}

Then simply inherit all controllers which need auditing from it

public class CustomerController : AuditableActionController

You can also use ActionFilters to do this however there will be more complexity to share the ICustomerService with the Controller.

Upvotes: 1

Darrel Miller
Darrel Miller

Reputation: 142024

You achieve these kind of cross cutting concerns with either a MessageHandler or ActionFilter.

Upvotes: 1

Related Questions