Reputation: 1316
I have am writing a multilingual site in MVC. I need to get the correct culture to inject into the SitesRepository, which is instantiated by a UnitOfWork pattern class.
My problem is that I'm getting the wrong culture returned in the constructor. Supposed to be getting back 'fr' yet receive 'en-GB'.
BaseController.cs - All controllers inherit from this.
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
string cultureName = null;
// Attempt to read the culture cookie from Request
HttpCookie cultureCookie = Request.Cookies["_culture"];
if (cultureCookie != null)
cultureName = cultureCookie.Value;
else
cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ?
Request.UserLanguages[0] : // obtain it from HTTP header AcceptLanguages
null;
// Validate culture name
cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe
// Modify current thread's cultures
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback, state);
}
}
My ListingsController instantiates a culture dependent UoW/Repository pattern in it's constructor.
public class ListingsController : BaseController
{
// Site Filtered Data
private SitesRepository db = null;
private Site site = null;
public ListingsController()
{
//string culture =
// Request.Cookies["_culture"] != null ?
// Request.Cookies["_culture"].Value :
// null;
db = new UnitOfWork().SitesRepository;
site = db.Site;
}
...
My UnitOfWork.cs:
public class UnitOfWork : IDisposable
{
public SitesRepository SitesRepository { get; private set; }
public UnitOfWork()
{
db = new PropertyInfoEntities();
var site = GetSite();
var culture = CultureHelper.GetCurrentCulture(); // = Thread.CurrentThread.CurrentCulture.Name;
var language = db.Languages.Single(l => l.CultureCode == culture);
SitesRepository = new SitesRepository(db, site, language.ID);
}
When I use actions from the ListingsController in another controller, then it returns the correct culture info as BaseController.BeginExecuteCore() has already run. However when using ListingsController directly it runs the constructor first, meaning that when the UoW pattern tries to get the culture info, it always returns en-GB and not the requested culture.
Any help on the best way to get the correct culture into the UoW/Repository of the ListingsController would be greatly appreciated. I've been stumped for the past 4 hours.
Upvotes: 1
Views: 1234
Reputation: 197
You answered your own question here:
When I use actions from the ListingsController in another controller, then it returns the correct culture info as BaseController.BeginExecuteCore() has already run. However when using ListingsController directly it runs the constructor first, meaning that when the UoW pattern tries to get the culture info, it always returns en-GB and not the requested culture.
So you have to create UoW not in constructor but in Controller Methods. You can create helper method (or property) to do it for you:
protected SitesRepository GetRepository()
{
if (db == null)
{
db = new UnitOfWork().SitesRepository;
}
return db;
}
and then use it like this:
public void SomeMethod()
{
SiteRepository repository = GetRepository();
// do actions with repository
}
It would be even better if you could create UnitOfWorkProvider
class with method like CreateUnitOfWork
, OpenUnitOfWork
or GetUnitOfWork
and then use it in your controller methods. If you do so you would be 99% sure (1% for weird errors) that you get UoW with proper culture.
Upvotes: 2