Question

I was wondering whether any people could help me please? I'm trying to create a site where the user logs in, it retrieves their chosen language from the database, and it uses that when setting the culture. There are also a number of settings about the user that would be retrieved at the same time as the user's language.

The culture/translations are handled via a base controller below (it's still a test version, but you will get the idea).

public abstract class BaseController : Controller
{

    //public UserRegistrationInformation UserSession;

    //public void GetUserInfo()
    //{
    //    WebUsersEntities db = new WebUsersEntities();
    //    UserSession = db.UserRegistrationInformations.Where(r => r.uri_UserID == WebSecurity.CurrentUserId).FirstOrDefault();
    //}


    protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
    {
        //GetUserInfo();


        string cultureName = null;
        // Change this to read from the user settings rather than a cookie

        /// Attempt to read the culture cookie from Request
        //HttpCookie cultureCookie = Request.Cookies["_culture"];
        //if (cultureCookie != null)
        //    cultureName = cultureCookie.Value;
        //else
            cultureName = Request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages
            //cultureName = "es-es";

            // 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);
    }


}

This was largely taken from http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx

I've been searching for how to pass the user's settings to the _layout rather than just the view. I found an interesting post here Pass data to layout that are common to all pages that works for me, I've created a base ViewModel, and any other ViewModels are inheriting it.

public abstract class ViewModelBase
{
    public string BrandName { get; set; }
    public UserRegistrationInformation UserSession;

    public void GetUserInfo()
    {
        WebUsersEntities db = new WebUsersEntities();
        UserSession = db.UserRegistrationInformations.Where(r => r.uri_UserID == WebSecurity.CurrentUserId).FirstOrDefault();
    }

}

To test with I've altered the existing change password model and control to:

public class LocalPasswordModel : ViewModelBase
{..........}

and

public ActionResult Manage(ManageMessageId? message)
    {

        //ViewModelAccounts vma = new ViewModelAccounts();
        //vma.GetUserInfo();
        LocalPasswordModel l = new LocalPasswordModel();
        l.GetUserInfo();
        l.BrandName = "blue";

        ViewBag.StatusMessage =
            message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
            : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
            : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
            : "";
        ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
        ViewBag.ReturnUrl = Url.Action("Manage");
        return View(l);
    }

Again this works perfectly, however I only want to retrieve the user's information the once. Currently I can do what I want by calling it in the BeginExecuteCore, and then again in the controller as above. How can I call this the once to be used everywhere? i.e. populate the BaseViewModel.

Thanks for any help or pointers you may be able to give!

Était-ce utile?

La solution

Ok. I've finally solved this.

I'm, creating a base model that all of my other view-models are going to inherit from. It can also be called directly in case any view doesn't require its own view-model.

public class ViewModelBase
{
    public UserSettings ProfileSettings;

    // Create a new instance, so we don't need to every time its called.
    public ViewModelBase()
    {
        ProfileSettings = new UserSettings();
    }

}

public class UserSettings // UserSettings is only used here and consumed by ViewModelBase, its the name there that is used throughout the application
{
    public string BrandName { get; set; }
    public UserRegistrationInformation UserSession;    
}

This is being generated in the basecontroller.

public abstract class BaseController : Controller
{
    public ViewModelBase vmb = new ViewModelBase();

    protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
    {
        string cultureName = null;
        int userid = 0;

        if (System.Web.Security.Membership.GetUser() != null)
        {
            //logged in
            userid = (int)System.Web.Security.Membership.GetUser().ProviderUserKey;

            WebUsersEntities db = new WebUsersEntities();
            vmb.ProfileSettings.UserSession = db.UserRegistrationInformations.Where(r => r.uri_UserID == userid).FirstOrDefault();
            vmb.ProfileSettings.BrandName = "test";

            cultureName = "es-es";
        }
        else
        {
            // not logged in                
            cultureName = Request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages
        }


        // 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);
    }
}

The other controllers all inherit from this controller. If any screen has a dedicated view-model it can retrieve the information from the model populated in the controller like this:

    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        LoginModel v = new LoginModel();

        v.ProfileSettings = vmb.ProfileSettings;

        ViewBag.ReturnUrl = returnUrl;
        return View(v);
    }

I hope that helps someone in the future.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top