i'm having some problems with to pass value from UserProfile to #Viewbag to show in Index.cshtml.
Let's explain:
When i'm do a Register of new user or Login, i'm trying to pass UserType field from UserProfile in a viewbag.
UserType is a custom field that i create on UserProfile to validate if the user is a "Musico" or "Ouvinte"
After debug application, I see that viewbag is taking NULL value.
This is the code that i try to get value from UserProfile in Register and Login post method:
LOGIN POST METHOD
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName,
model.Password,
persistCookie: model.RememberMe))
{
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
var userType = user.UserType;
TempData["UserType"] = userType; //Taking UserType from User Profile
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
REGISTER POST METHOD
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles
.SingleOrDefault(u => u.UserName == username);
var userType = user.UserType;
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new
{
UserType = model.UserType
});
WebSecurity.Login(model.UserName, model.Password);
// string currentUserType = u.UserType;
TempData["UserType"] = userType;//Get the userType to validate on _Layout
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
return View(model);
}
Calling viewbag in part of Index page
<p>
#if (Request.IsAuthenticated && ViewBag.UserType.Equals("Musico"))
{
<span>musico</span>
}
else if (Request.IsAuthenticated && ViewBag.UserType.Equals("Ouvinte"))
{
<span>ouvinte</span>
} else{
<span>teste</span>
}
</p>
HomeController
public ActionResult Index()
{
ViewBag.UserType = TempData["UserType"];
return View();
}
See this article for a good explanation, When to use ViewBag, ViewData, or TempData.
.. once the controller redirects, the ViewBag and ViewData will contain null values. If you inspect the TempData object with debugging tools after the redirect you'll see that it is fully populated.
Do this instead:
TempData["UserType"] = userType;
Change your view accordingly i.e.
#{var tempUserType = TempData["UserType"]} // in the top
And then use it as you would with the ViewBag
The ViewBag is lost because of the redirect.
An easy solution would be to use TempData, which only remains valid after one extra request. After that, it is normally gone, there is however a Keep method.
From MSDN:
However, the data in a TempDataDictionary object persists only from
one request to the next, unless you mark one or more keys for
retention by using the Keep method. If a key is marked for retention,
the key is retained for the next request.
Example:
[Authorize]
public class AccountController : Controller
{
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// do stuff
TempData["UserType"] = userType;
return RedirectToAction("Index", "Home");
}
// something went wrong, return view
return View(model);
}
}
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.UserType = TempData["UserType"];
return View();
}
}
Related
I want to use one page for showing two different texts based on the action the request coming from, if this request comes directly from the Index it shows some welcome text, and if it comes from the Create form it shows some other text:
public ActionResult Index(bool? ticketSent)
{
if (ticketSent == true)
ViewBag.IfcText = "done";
else
ViewBag.IfcText = "hello";
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "TicketNumber,OwnerName,Email,LaptopModelNumber,Subject,Description,ComplainDate")] Ticket ticket)
{
if (ModelState.IsValid)
{
db.Tickets.Add(ticket);
db.SaveChanges();
return RedirectToAction("Index", new { ticketSent = true });
}
return View(ticket);
}
but when the request comes from the Create action the Url contains the query string, http://localhost:54401/?ticketSent=True, thus if the user refreshed the browser or even navigate to it any time he gets the same page indicating that the form sent successfully, I want to ensure it's being shown after he creates the form only without the query string.
This is the view:
#{if (ViewBag.IfcText == "hello")
{
<h2>Encountering a problem? We are here to help</h2>
<h3>
#Html.ActionLink("Contact our Support Team", "Create")
</h3>
}
else if (ViewBag.IfcText == "done")
{
#:<h2>We received it, we will be in contact with you in 24 hrs.</h2>
}
}
use TempData to store the flag. It will only be available on the redirect from the previous request, which is what you wanted.
Check out this article to get a better understanding
When to use ViewBag, ViewData, or TempData in ASP.NET MVC 3 applications
The concept still applies for recent versions of MVC
const string ticketSentKey = "ticketSent";
public ActionResult Index()
{
var ticketSent = false;
if(TempData.ContainsKey(ticketSentKey) && TempData[ticketSentKey] is bool)
ticketSent = (bool)TempData[ticketSentKey];
if (ticketSent == true)
ViewBag.IfcText = "done";
else
ViewBag.IfcText = "hello";
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "TicketNumber,OwnerName,Email,LaptopModelNumber,Subject,Description,ComplainDate")] Ticket ticket)
{
if (ModelState.IsValid)
{
db.Tickets.Add(ticket);
db.SaveChanges();
TempData[ticketSentKey] = true;
return RedirectToAction("Index");
}
return View(ticket);
}
Using MVC 5 and Identity 2.0, I add custom properties to ApplicationUserClass like FirstName, LastName, Address. Those will be new fields in the database. When the user register to the application he/she will enter the email address and password only. After they register, and they log in I want to force them to complete their profile, or at least each time they login they should be redirected to the profile completion page where they can mention the FirstName, Lastname and Address. Afther they complete the profile they will not be redirected to complete profile page each time they login.
Something like:
if UserProfile != Completed
go to CompleteProfilePage
else
go to MainPage
You can try a global filter. This will not allow your users to bypass the check by modifying the URL manually.
public class ProfileCompletionCheckAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//this will prevent redirect for still unauthenticated users
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
return;
//replace these to actual values of your profile completion action and controller
string actionOfProfilePage = "Index";
string controlerOfProfilePage = "Home";
bool areWeAlreadyInProfilePage = filterContext.ActionDescriptor.ActionName == actionOfProfilePage
&& filterContext.ActionDescriptor.ControllerDescriptor.ControllerName == controlerOfProfilePage;
if (areWeAlreadyInProfilePage) //this will prevent redirect loop
return;
bool isProfileComplete = false; //replace this with your custom logic
if (!isProfileComplete)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", controlerOfProfilePage },
{ "action", actionOfProfilePage }
});
}
}
}
To enable it, just add this to FilterConfig.cs
filters.Add(new ProfileCompletionCheckAttribute());
In your AccountController something like this :
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
Upgrade like this
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
UsersContext dbu = new UsersContext();
UserProfile usr = dbu.UserProfiles.Where(u => u.UserName == model.UserName).First();
if (usr.FirstName == null) return RedirectToAction("Profile", "Account");
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
I have MVC.Net C# Login page and I decided to make some fancy changes, and all of the sudden my login page stoped working.
I need your help , somebody else to look at my code and may be see what I couldn't find. during debugging, it returns all true but don't go into index page. What do you think ? what is my problem that I can't see!
Here is my controller:
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (model.IsUserExist(model.EMP_ID, model.EMP_PASSWORD))
{
FormsAuthentication.SetAuthCookie(model.EMP_ID, false);
}
else
{
ModelState.AddModelError("", "The User ID or Password provided is incorrect.");
}
}
return View(model);
}
You are transferring it to any other view, you can use return RedirectToAction("Actionname","controllername","params if any");
// POST: /Account/Login
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (model.IsUserExist(model.EMP_ID, model.EMP_PASSWORD))
{
FormsAuthentication.SetAuthCookie(model.EMP_ID, false);
//change here
return RedirectToAction("Actionname","controllername","params if any");
}
else
{
ModelState.AddModelError("", "The User ID or Password provided is incorrect.");
}
}
return View(model);
}
I want the Logout link to carry out a process located in HomeController and not to display a new View. How do I go about structuring this?
Controller method:
public ActionResult LogoutProcess()
{
previousLoggedIn = WebSecurity.CurrentUserName;
WebSecurity.Logout();
return RedirectToAction("Logout", "Home");
}
public ActionResult Logout(HomeModels.LogoutModel model)
{
model.PreviouslyLoggedInUsername = previousLoggedIn;
return View(model);
}
View:
Logout
You can use the standard link, targeting that action
#Url.Action("LogoutProcess", "Home")
The "trick" is in Redirection to some other View at the end of your LogoutProcess() action:
public ActionResult LogoutProcess()
{
// TempData to transfer user name
TempData["previousLoggedIn"] = WebSecurity.CurrentUserName;
WebSecurity.Logout();
return RedirectToAction("Logout", "Home");
}
public ActionResult Logout(HomeModels.LogoutModel model)
{
// fill model from TempData
model.PreviouslyLoggedInUsername = TempData["previousLoggedIn"];
return View(model);
}
The CurrentUserName is passed to other action via TempData
Try this:
public ActionResult LogoutProcess()
{
WebSecurity.Logout();
//return null;
Return RedirectToAction("Index");//or whatever page you want to display after logout.
}
Have you considered a no content http status code result?
return new HttpStatusCodeResult(HttpStatusCode.NoContent);
I've recently created an ASP.NET MVC 2 application, which works perfectly in the development environment. However, when I deploy it to the server (123-reg Premium Hosting), I can access all of the expected areas - except the Account controller (www.host.info/Account). This then attempts to redirect to the Error.aspx page (www.host.info/Shared/Error.aspx) which it cannot find. I've checked that all of the views have been published, and they're all in the correct place.
It seems bizarre that two other controllers can be accessed with no problems, whereas the Account controller cannot be found. I have since renamed the AccountController to SecureController, and all of the dependencies, to no avail.
The problem with not being able to find the Error.aspx page also occurs on the development environment.
Any ideas would be greatly appreciated.
Thanks,
Chris
1) Can you check the DLL that was published to make sure that type exists in the assembly? Are any special modifiers applied to the Account controller compared to the other controllers (such as specific attributes, base classes, additional code)?
2) Can you verify what HttpMethod you are using to request the page? I'm assuming just a normal GET, but it may be coming in as a different verb causing you not to find your action method.
3) Are you using any custom routing, or just the standard {controller}/{action}/{id} setup?
The version of IIS on the server is 7.0, of which I have no control over.
The account controller code all works perfectly on the development environment, and the code is as follows:
[HandleError]
public class SecureController : Controller
{
private UserManager manager;
public IFormsAuthenticationService FormsService { get; set; }
public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
}
// Lazy man's Dependency Injection for now, use Ninject later!
public SecureController(UserManager mgr) { manager = mgr; }
public SecureController() : this(new UserManager(new PortfolioDataDataContext())) { }
// **************************************
// URL: /Account/LogOn
// **************************************
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
// **************************************
// URL: /Account/LogOff
// **************************************
public ActionResult LogOff()
{
FormsService.SignOut();
return RedirectToAction("Index", "Home");
}
// **************************************
// URL: /Account/Register
// **************************************
public ActionResult Register()
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View();
}
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus = manager.CreateUser(model.UserName, model.Password, model.Email, model.FullName);
if (createStatus == MembershipCreateStatus.Success)
{
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View(model);
}
// **************************************
// URL: /Account/ChangePassword
// **************************************
[Authorize]
public ActionResult ChangePassword()
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View();
}
[Authorize]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
{
return RedirectToAction("ChangePasswordSuccess");
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
// If we got this far, something failed, redisplay form
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View(model);
}
// **************************************
// URL: /Account/ChangePasswordSuccess
// **************************************
public ActionResult ChangePasswordSuccess()
{
return View();
}
}