xUnit testing controller with error when instantiating JWT token provider - c#

I have a controller in my WebAPI (not MVC or Core) using .Net 4.8 that I'm trying to test with xUnit.
Before I proceed, the way it is setup may not be correct for unit testing, but it is what I have been given and I don't know any better at this stage, any pointers in this regard is welcome.
The main problem in the controller is the immediate declaration/instantiation of ApiOAuthProvider. As it creates the object, it in-turn does an immediate declaration/instantiation of JwtTokenProvider. This is where the error occurs, inner exception:
Message "Could not load file or assembly
'System.Configuration.ConfigurationManager, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot
find the file specified."
But I'm jumping ahead I'll show the code
Controller:
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TA.Services.BL.BusinessLogic;
using TA.Services.WebAPI.Providers;
using TA.Services.DTO.DTO;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using TA.Services.BL.Interface;
namespace TA.Services.WebAPI.Controllers
{
public class AccountsController : ApiController
{
private readonly ApiOAuthProvider _jwtTokenProvider = new ApiOAuthProvider();
private readonly ICommonBL _commonBL;
private readonly ISystemSettingsBL _systemSettingsBL;
public AccountsController(ICommonBL commonBL, ISystemSettingsBL systemSettingsBL)
{
_commonBL = commonBL;
_systemSettingsBL = systemSettingsBL;
}
...
// GET: JwtToken
[HttpPost]
//[EnableCors("*", "*", "*")]
public JObject Token(User loginUserCredentials)
{
// first check the user name & password is valid one before generating token for that user.
var user = _commonBL.GetUserInformation(loginUserCredentials.UserName);
var accessToken = _jwtTokenProvider.GenerateToken(user);
return accessToken;
}
}
}
ApiOAuthProvider:
namespace TA.Services.WebAPI.Providers
{
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Web.Http.Cors;
using TA.Services.DTO.DTO;
using static TA.Services.WebAPI.Providers.JWTHelper;
[EnableCors("*", "*", "*")]
public class ApiOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly JwtTokenProvider _jwtTokenProvider = new JwtTokenProvider();
[EnableCors("*", "*", "*")]
public JObject GenerateToken(User userDetail)
{
...
return tokenResponse;
}
public static AuthenticationProperties CreateProperties(string userName, Status apiData)
{
...
return new AuthenticationProperties(data);
}
}
}
JwtTokenProvider:
namespace TA.Services.WebAPI.Providers
{
using System;
using System.Configuration;
using System.Security.Claims;
using System.Text;
using System.Web.Configuration;
using System.Web;
using Microsoft.Owin.Security;
using TA.Services.BL.Interface;
using TA.Services.DTO.DTO;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
public class JwtTokenProvider : ISecureDataFormat<AuthenticationTicket>
{
private static string plainTextSecurityKey = ((MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey")).ValidationKey;
private readonly Microsoft.IdentityModel.Tokens.SymmetricSecurityKey _signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
private readonly IAuditsBL _auditsBL;
public string Protect(AuthenticationTicket data)
{
var signedAndEncodedToken = string.Empty;
...
return signedAndEncodedToken;
}
public AuthenticationTicket Unprotect(string signedAndEncodedToken)
{
ClaimsIdentity idenity = null;
...
return new AuthenticationTicket(idenity, new AuthenticationProperties());
}
}
}
My xUnit test class:
using Moq;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Principal;
using System.Web.Http;
using TA.Services.BL.Interface;
using TA.Services.DTO.DTO;
using TA.Services.WebAPI.Controllers;
using TA.Services.WebAPI.Providers;
using Xunit;
namespace TA.Services.WebAPI.Tests.Controllers
{
public class AccountsControllerTests : BaseUnitTest
{
private readonly Mock<ICommonBL> _commonBLMock;
private readonly Mock<ISystemSettingsBL> _systemSettingsBLMock;
private readonly AccountsController _accountsController;
public AccountsControllerTests()
{
_commonBLMock = new Mock<ICommonBL>();
_systemSettingsBLMock = new Mock<ISystemSettingsBL>();
_accountsController = new AccountsController(_commonBLMock.Object, _systemSettingsBLMock.Object);
}
...
}
}
The exception occurs here in JwtTokenProvider:
private readonly Microsoft.IdentityModel.Tokens.SymmetricSecurityKey _signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
StackTrace:
at TA.Services.WebAPI.Providers.JwtTokenProvider..ctor() in C:\TA\Repos\April 20 2021\TADev\Service\TA.Services\TA.Services.WebAPI\Providers\JwtTokenProvider.cs:line 19
at TA.Services.WebAPI.Providers.ApiOAuthProvider..ctor() in C:\TA\Repos\April 20 2021\TADev\Service\TA.Services\TA.Services.WebAPI\Providers\ApiOAuthProvider.cs:line 23
at TA.Services.WebAPI.Controllers.AccountsController..ctor(ICommonBL commonBL, ISystemSettingsBL systemSettingsBL) in C:\TA\Repos\April 20 2021\TADev\Service\TA.Services\TA.Services.WebAPI\Controllers\AccountsController.cs:line 27
at TA.Services.WebAPI.Tests.Controllers.AccountsControllerTests..ctor() in C:\TA\Repos\April 20 2021\TADev\Service\TA.Services\Testing\TA.Services.WebAPI.Tests\Controllers\AccountsControllerTests.cs:line 26
Sub-questions:
Maybe I'm going down the wrong path, however should I mock ApiOAuthProvider, in order to do that I need to inject it, in order to do that, I need to create an interface and registry it as a service, but this doesn't sound right.
Do I just need to create a valid token.
Maybe it really can't find the System.Configuration.ConfigurationManager
Main Question: How should I go about resolving this?
Note: The application works just fine outside of this test, under normal execution.
[Update] Changed controller have ApiOAuthProvider injected
public class AccountsController : ApiController
{
private readonly ApiOAuthProvider _jwtTokenProvider;
private readonly ICommonBL _commonBL;
private readonly ISystemSettingsBL _systemSettingsBL;
public AccountsController(ApiOAuthProvider jwtTokenProvider, ICommonBL commonBL, ISystemSettingsBL systemSettingsBL)
{
_commonBL = commonBL;
_systemSettingsBL = systemSettingsBL;
_jwtTokenProvider = jwtTokenProvider;
}
Added ApiOAuthProvider to services in startup:
services.AddSingleton<ApiOAuthProvider>();
Changed test script:
public class AccountsControllerTests : BaseUnitTest
{
private readonly Mock<ApiOAuthProvider> _apiOAuthProviderMock;
private readonly Mock<ICommonBL> _commonBLMock;
private readonly Mock<ISystemSettingsBL> _systemSettingsBLMock;
private readonly AccountsController _accountsController;
public AccountsControllerTests()
{
_apiOAuthProviderMock = new Mock<ApiOAuthProvider>();
_commonBLMock = new Mock<ICommonBL>();
_systemSettingsBLMock = new Mock<ISystemSettingsBL>();
_accountsController = new AccountsController(_apiOAuthProviderMock.Object, _commonBLMock.Object, _systemSettingsBLMock.Object);
}
...
Debugged the test and it kept going until it got to the same error. Doesn't seem to mock very well without an interface.
[Update End]

Related

Overriding dispose method in multiple child classes

I am currently using Xunit to write some integration testing in my .NET Core project. As part of this, I am setting up the data and other information before running a test in my custom class.
using Microsoft.AspNetCore.TestHost;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace XUnitTestProject1
{
public class BaseClassFixture<TStartup> : IAsyncLifetime where TStartup : class
{
private readonly TestServer _server;
public HttpClient Client { get; }
public BaseClassFixture()
{
Client = new HttpClient();
Client.BaseAddress = new Uri("https://apple.com");
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_server?.Dispose();
this.Client?.Dispose();
}
}
public Task DisposeAsync()
{
return Task.CompletedTask;
}
public Task InitializeAsync()
{
throw new NotImplementedException();
}
}
}
My first Child Class:
using Microsoft.AspNetCore.TestHost;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace XUnitTestProject1
{
public class GoogleTestClassFixture<TStartUp> : BaseClassFixture<TStartUp>, IAsyncLifetime where TStartUp : class
{
private readonly TestServer _server;
public HttpClient GoogleClient { get; }
public GoogleTestClassFixture()
{
GoogleClient = new HttpClient();
GoogleClient.BaseAddress = new Uri("https://google.com");
GoogleClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public void Dispose()
{
_server?.Dispose();
GoogleClient?.Dispose();
base.Dispose(true);
}
public Task DisposeAsync()
{
throw new NotImplementedException();
}
public Task InitializeAsync()
{
throw new NotImplementedException();
}
}
}
My Second Child Class:
using Microsoft.AspNetCore.TestHost;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace XUnitTestProject1
{
public class FaceBookTestClassFixture<TStartUp> : BaseClassFixture<TStartUp>, IAsyncLifetime where TStartUp : class
{
private readonly TestServer _server;
public HttpClient FaceBookClient { get; }
public FaceBookTestClassFixture()
{
FaceBookClient = new HttpClient();
FaceBookClient.BaseAddress = new Uri("https://facebook.com");
FaceBookClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public void Dispose()
{
_server?.Dispose();
FaceBookClient?.Dispose();
base.Dispose(true);
}
public Task DisposeAsync()
{
throw new NotImplementedException();
}
public Task InitializeAsync()
{
throw new NotImplementedException();
}
}
}
When I run all the tests in my test explorer at once, some times I'm getting the error "Cannot access a dispose object". I am assuming, this is happening because some times the tests related to one test fixture are running and the object is disposed, and the other test fixture is unable to access already disposed of items from the base Class fixture.
My First Tests looks something like this:
public class GoogleTests
{
private readonly HttpClient _googleClient;
private readonly HttpClient _baseClient;
public GoogleTests(GoogleTestClassFixture<StartUp> fixture)
{
_googleClient = fixture.GoogleClient;
_baseClient = fixture.Client;
}
[Fact]
public async Task ValidateFirstClient()
{
var getDetails = await _googleClient.GetAsync("//someRoute");
var uri = new Uri("https://someRandom.com");
var postDetails = await _baseClient.PutAsync(uri, getDetails.Content);
var response = await postDetails.Content.ReadAsStringAsync();
dynamic dynamicResponse = JObject.Parse(response);
((int)dynamicResponse.myProperty).Should().Be(0);
}
}
My Second Test Class:
using FluentAssertions;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace XUnitTestProject1
{
public class FaceBookTests
{
private readonly HttpClient _fbClient;
private readonly HttpClient _baseClient;
public FaceBookTests(FaceBookTestClassFixture<StartUp> fixture)
{
_fbClient = fixture.FaceBookClient;
_baseClient = fixture.Client;
}
[Fact]
public async Task ValidateFirstClient()
{
var getDetails = await _fbClient.GetAsync("//someRoute");
var uri = new Uri("https://someRandom.com");
var postDetails = await _baseClient.PutAsync(uri, getDetails.Content);
var response = await postDetails.Content.ReadAsStringAsync();
dynamic dynamicResponse = JObject.Parse(response);
((int)dynamicResponse.myProperty).Should().Be(0);
}
}
}
enter code here
How can I solve this issue, and make sure the object is not disposed until it finishes running all the tests?
Note: I have created a simple web application project just to get the startup.cs class as a reference in my test project

InvalidOperationException: Unable to resolve service for type while attempting to activate

I am creating ASP.NET CORE project using DI and Repository Pattern. When I run project I get this type of error
InvalidOperationException: Unable to resolve service for type
'AD.BLL.Servisi.IKorisnikServis' while attempting to activate
'AD.Web.Controllers.KorisnikController'.
Here is my interface class
using System;
using System.Collections.Generic;
using System.Text;
namespace AD.BLL.Interfejsi
{
public interface IKorisnik
{
public string VratiKorisnike();
}
}
And here is my Service class which call this interface
using AD.BLL.Interfejsi;
using AD.Web.Data;
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
namespace AD.BLL.Servisi
{
public class IKorisnikServis : IKorisnik
{
private ApplicationDbContext _db;
public IKorisnikServis(ApplicationDbContext db)
{
_db = db;
}
public string VratiKorisnike()
{
System.DirectoryServices.DirectoryEntry rootDSE = new System.DirectoryServices.DirectoryEntry("LDAP://RootDSE");
var defaultNamingContext = rootDSE.Properties["defaultNamingContext"].Value;
DirectorySearcher dssearch = new DirectorySearcher("LDAP://" + defaultNamingContext);
dssearch.Filter = "(sAMAccountName=ABCDEFGHI)";
SearchResult sresult = dssearch.FindOne();
System.DirectoryServices.DirectoryEntry dsresult = sresult.GetDirectoryEntry();
var Ime = dsresult.Properties["Ime"][0].ToString();
var Prezime = dsresult.Properties["Prezime"][0].ToString();
var LoginName = dsresult.Properties["LoginName"][0].ToString();
var Status = dsresult.Properties["Status"][0].ToString();
var AccountExpired = dsresult.Properties["AccountExpired"][0].ToString();
var PassNevExp = dsresult.Properties["PassNevExp"][0].ToString();
var DomenskaGrupa = dsresult.Properties["DomenskaGrupa"][0].ToString();
var Email = dsresult.Properties["Email"][0].ToString();
return Ime;
}
}
}
Here is my ApplicationDbContext class
using AD.Models.DbModels;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AD.Web.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Korisnik> Korisnici { get; set; }
}
}
And here is my Controller action
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AD.BLL.Servisi;
using Microsoft.AspNetCore.Mvc;
namespace AD.Web.Controllers
{
public class KorisnikController : Controller
{
private IKorisnikServis _korisnikServis;
public KorisnikController(IKorisnikServis korisnikServis)
{
_korisnikServis = korisnikServis;
}
public IActionResult VratiKorisnike()
{
_korisnikServis.VratiKorisnike();
return View();
}
public IActionResult Index()
{
return View();
}
}
}
And in Startup.cs I register IKorisnik and IKorisnikServic
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<IKorisnik, IKorisnikServis>();
}
I checked everything but I cannot see where I made mistake. Any help ?
In your Controller you need to create the filed of type IKorisnik which is your interface instead of IKorisnikServis, So your constructor should be like this:
private IKorisnik _korisnikServis;
public KorisnikController(IKorisnik korisnikServis)
{
_korisnikServis = korisnikServis;
}
However, I would strongly recommend to consider another name for your IKorisnikServis class (KorisnikServis for example) as the prefix I is mostly using to indicate an interface, in this case it is also misleading and I believe that was the reason you have used it in your controller by mistake.

XUnit Test different results under netcoreapp1.1 and net462

I created a XUnit test projects in VS 2017, its target framework is netcoreapp1.1, and below code works correctly.
using Xunit;
using Xunit.Abstractions;
using Xunit.Ioc.Autofac;
namespace XUnitTestProject2
{
[UseAutofacTestFramework]
public class MyAwesomeTests
{
public MyAwesomeTests()
{
}
public MyAwesomeTests(ITestOutputHelper outputHelper)
{
_outputHelper = outputHelper;
}
[Fact]
public void AssertThatWeDoStuff()
{
_outputHelper.WriteLine("Hello");
}
private readonly ITestOutputHelper _outputHelper;
}
}
using Autofac;
using System.Reflection;
using Xunit;
using Xunit.Abstractions;
using Xunit.Ioc.Autofac;
using Xunit.Sdk;
[assembly: TestFramework("XUnitTestProject2.ConfigureTestFramework", "XUnitTestProject2")]
namespace XUnitTestProject2
{
public class ConfigureTestFramework : AutofacTestFramework
{
private const string TestSuffixConvention = "Tests";
public ConfigureTestFramework(IMessageSink diagnosticMessageSink)
: base(diagnosticMessageSink)
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(typeof(ConfigureTestFramework).GetTypeInfo().Assembly)
.Where(t => t.Name.EndsWith(TestSuffixConvention));
builder.RegisterType<TestOutputHelper>().AsSelf().As<ITestOutputHelper>().InstancePerLifetimeScope();
// configure your container
// e.g. builder.RegisterModule<TestOverrideModule>();
Container = builder.Build();
}
}
}
But, if I change the targetframework to net462, there will not tests be found.
Did i miss anything?
Any help would be appreciated.

WebApi Route returns Not Found in Orchard Module

I am creating an Orchard module where i want to add a WebApi controller.
My Module.txt:
Name: ModuleName
AntiForgery: enabled
Author: The Orchard Team
Website: http://orchardproject.net
Version: 1.0
OrchardVersion: 1.0
Description: Description for the module
Features:
ModuleName:
Description: Description for feature ModuleName.
I have added an ApiRoutes class:
using Orchard.Mvc.Routes;
using Orchard.WebApi.Routes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
namespace ModuleName
{
public class ModuleNameApiRoutes : IHttpRouteProvider
{
public void GetRoutes(ICollection<RouteDescriptor> routes)
{
foreach (var routeDescriptor in GetRoutes())
{
routes.Add(routeDescriptor);
}
}
public IEnumerable<RouteDescriptor> GetRoutes()
{
return new[] {
new HttpRouteDescriptor {
Name = "ModuleName",
Priority = 5,
RouteTemplate = "api/modulename/{controller}/{id}",
Defaults = new {
area = "ModuleName",
id = RouteParameter.Optional
}
}
};
}
}
}
Then i have added an apicontroller:
using Newtonsoft.Json.Linq;
using Orchard;
using Orchard.Data;
using ModuleName.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace ModuleName.Controllers
{
public class ConsumptionController : ApiController
{
public IOrchardServices Services { get; private set; }
private readonly IRepository<Vessel_ConsumptionPartRecord> _repository;
public ConsumptionController(IOrchardServices orchardServices,IRepository<Vessel_ConsumptionPartRecord> repository)
{
_repository = repository;
}
// GET: Home
public HttpResponseMessage Get()
{
...
}
}
}
I am on Localhost and the home url is:
http://localhost:30321/OrchardLocal
When i go to
http://localhost:30321/OrchardLocal/api/ModuleName/Consumption
I get a Not Found page.
Can anyone shed some light?
Your GET method does not have a parameter id. That might be it
I had this earlier today with a web api call. Turns out changing the link worked for me.
I went from using http://localhost:30321/Orchard.web/api/ModuleName/Get to using http://localhost:30321/api/ModuleName/Get when I was testing using the Postman Chrome extension

Why is my C# MVC4 Session Wrapper Service not working?

I am trying to implement a wrapper for my session (Loose coupling so it is easy to make changes later) but I am having problems, either the storing into the session is failing, or the retrieval but I do not know which.
I would greatly appreciate it if you could take a look at my code and tell me if there is anything obviously wrong, or a better way of doing what I am trying to do. I basically want to display different things to different types of user, but when I try to access the user in the ViewContext it is null.
Any links to tutorials or examples would be gratefully accepted.
Here is my code:
User and WEB_USER_LEVEL have a one to many relationship
I have used Entity Framework to create models from my existing database
I am currently in the early stages of the project and the User is not coming from the database yet (as the structure will change) so I am creating a new User and populating it before using CurrentUserService.Login(user). i have tried pulling a user out of the data base and logging that user in but it still does not work.
ICurrentUserService.cs (in Infrastructure folder)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MyProject.Infrastructure
{
public interface ICurrentUserService
{
User CurrentUser { get; }
void SetCurrentUser(WEB_USER user);
void SetAdminStatus(bool type);
bool GetAdminStatus { get; }
void SetManagerStatus(bool type);
bool GetManagerStatus { get; }
void Login(User user);
void Logout();
int? TryGetCurrentUserId();
}
}
CurrentUserService.cs (in Infrastructure folder)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MyProject.Controllers;
using MyProject.Infrastructure.Filters;
namespace MyProject.Infrastructure
{
public class CurrentUserService : ICurrentUserService
{
public const string CurrentUserKey = "CurrentUser";
public const string CurrentUserIdKey = "CurrentUserId";
public const string IsAdminKey = "IsAdmin";
public const string IsManagerKey = "IsManager";
private readonly IDb _db;
public CurrentUserService() : this(new Db()) { }
public CurrentUserService(IDb db)
{
_db = db;
}
public User CurrentUser
{
get
{
return (User)HttpContext.Current.Items[CurrentUserKey];
}
}
public void SetCurrentUser(User user)
{
HttpContext.Current.Items[CurrentUserKey] = user;
}
public void SetAdminStatus(bool type)
{
HttpContext.Current.Session[IsAdminKey] = type;
}
public bool GetAdminStatus
{
get { return (bool)HttpContext.Current.Session[IsAdminKey]; }
}
public void SetManagerStatus(bool type)
{
HttpContext.Current.Session[IsManagerKey] = type;
}
public bool GetManagerStatus
{
get { return (bool)HttpContext.Current.Session[IsManagerKey]; }
}
public void Login(User user)
{
HttpContext.Current.Session[CurrentUserIdKey] = user.ID;
HttpContext.Current.Items[CurrentUserKey] = user;
SetManagerStatus(user.WEB_USER_LEVEL.IsManager);
SetAdminStatus(user.WEB_USER_LEVEL.RefID == 1 ? true : false);
}
public void Logout()
{
HttpContext.Current.Items[CurrentUserKey] = null;
HttpContext.Current.Session[CurrentUserIdKey] = null;
SetManagerStatus(false);
SetAdminStatus(false);
}
public int? TryGetCurrentUserId()
{
return HttpContext.Current.Session[CurrentUserIdKey] as int?;
}
}
}
Extensions.cs (in Infrastructure folder)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Infrastructure
{
public static class Extensions
{
public static User CurrentUser(this ViewContext view)
{
return (User)view.HttpContext.Items[CurrentUserService.CurrentUserKey];
}
}
}
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyProject.Infrastructure;
using MyProject.Infrastructure.Filters;
using MyProject.ViewModels;
using MyProject.Models;
using System.Data.Objects;
namespace MyProject.Controllers
{
public class HomeController : BaseController
{
readonly IDb _db;
readonly ICurrentUserService _currentUserService;
readonly IErrorReporter _errorReporter;
public HomeController() : this(new Db(), new CurrentUserService(), new ErrorReporter()) { }
public HomeController(IDb db, ICurrentUserService currentUserService, IErrorReporter errorReporter)
{
_db = db;
_currentUserService = currentUserService;
_errorReporter = errorReporter;
}
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Login(FormCollection form)
{
// Create new user and populate
_currentUserService.Login(user);
return RedirectToAction("Home");
}
public ActionResult Home()
{
return View();
}
}
}
Trying to access in ViewContext in _Layout.cshtml when the Home view is loaded
#using MyProject.Infrastructure
#if (ViewContext.CurrentUser() != null && ViewContext.CurrentUser().WEB_USER_LEVEL.IsManager)
{
#RenderPage("~/Views/Shared/_Menu.cshtml")
}
But ViewContext.CurrentUser() is always null.
Thank you for your help!
Instead of creating an extension method on top of ViewContext, I would suggest that you create a ViewModel for your view and pass into it the data that your view needs. Remember, any external data that a view needs should be fed into it through a ViewModel. This makes for a clean one to one relationship that's easy to follow.

Categories

Resources