ASP.NET Entity Framework success message after registration - asp.net-mvc

I am really trying hard to make a popup message (success or error) when the user has finished registration. So in the AccountController, I made a ViewBag but since it redirects to Login right away, I've noticed that the message is not appearing or popping up.
How do I show the message?
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
....
ViewBag.message= "Registered Successfully";
return RedirectToAction("Login", "Account");
}
}
_Layout view:
<div class="container body-content">
#if (ViewBag.message!= null)
{
if (ViewBag.message.Equals("Registered Successfully"))
{
<div class="alert alert-success fade in">
×
<strong>Success!</strong> #ViewBag.message
</div>
}
}
#RenderBody()
</div>

You may use TempData instead of the ViewBag
if (ModelState.IsValid)
{
TempData["Message"] = "Registered Successfully";
return RedirectToAction("Login", "Account");
}
In your view:
<div class="container body-content">
#if (TempData["Message"] != null)
{
...
}
#RenderBody()
</div>

Related

Checkbox Form Submit trigger Logout in Identity EntityFramework on _loginpartial-C# asp.net MVC

I have a checkbox(justdoit) on asp.net MVC create view. If checkbox checked, it submits#onclick = "document.forms[0].submit() value and according to that, if else condition disable or enable other dropbox form("Status) in view.It was working without problem. After I integrated authorization to page(Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.10), I added _loginpartial to _layout.cshtml page. Then I log in page with authorised user and enter create item page,when I check to checkbox(onlick submit works), log out is trigered and I log out the site and find myself on the indexpage. After that I tried to create item without login, it works without problem. Therefore I think checkbox submit trigger the logout.(Project.Identity.Pages.Account.LogoutModel: Information: User logged out.) How Can I solve that problem?
Thank you for answer in advance
Code in the view:
#Html.CheckBox("Justdoit", false, new { #onclick = "document.forms[0].submit();" })
Justdoit
<br />
#if(Convert.ToBoolean(ViewBag.Justdoit))
{
<div class="form-group">
<label asp-for="Status" class="control-label">Status (Choose One)</label>
<select asp-for="Status" class="form-control" id="Status" disabled>
<option>Completed</option>
</select>
<span asp-validation-for="Status" class="text-danger"></span>
</div>
}
else
{
<div class="form-group">
<label asp-for="Status" class="control-label">Status (Choose One)</label>
<select asp-for="Status" class="form-control" id="Status" >
<option>Completed</option>
<option>Plan</option>
<option>Do</option>
<option>Study</option>
<option>Act</option>
</select>
<span asp-validation-for="Status" class="text-danger"></span>
</div>
}
</td>
Code in the _loginpartial
<li class="nav-item">
<form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="#Url.Action("Index", "Home", new { area = "" })">
<button id="logout" type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
Item controller- It logs out before calling ViewBag.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>Create(bool Justdoit,[Bind("Id,Title,Description,MainBody,Team,Owner,StartDate,Status,Justdoit,Category")] Suggestion suggestion)
{
ViewBag.Justdoit = Justdoit;
if (ModelState.IsValid)
{
_context.Add(suggestion);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(suggestion);
}
Logout model View
#page
#model LogoutModel
#{
ViewData["Title"] = "Log out";
}
<header>
<h1>#ViewData["Title"]</h1>
#{
if (User.Identity.IsAuthenticated)
{
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="#Url.Page("/", new { area = "" })" method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Click here to Logout</button>
</form>
}
else
{
<p>You have successfully logged out of the application.</p>
}
}
</header>
Logout model cshtml.cs file
public class LogoutModel : PageModel
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger<LogoutModel> _logger;
public LogoutModel(SignInManager<ApplicationUser> signInManager, ILogger<LogoutModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
// This needs to be a redirect so that the browser performs a new
// request and the identity for the user gets updated.
return RedirectToPage();
}
}
}
Enable or Disable form based on Condition in ASP.Net MVC. Condition is created by clicking the checkbox. I want to use that feature on the authorized page.

MVC, how to temporary (5 seconds) display a View with the message, while being redirected to another View

I have an MVC application.
I have a View A that renders partial View _B.
View A has a logic that defines when to show partial View _B and when not:
#if (!(bool)ViewData["PasswordChanged"])
{
<div style="margin-top:20px;">
<div>
#Html.Partial("~/Views/_B.cshtml");
</div>
</div>
}
else
{
<div id="redirect" style="margin-top:20px;">
<div style="color:green;">
#ViewBag.Message
</div>
<div>
Please wait while you are redirected...
</div>
</div>
I'm looking for the solution that will help me to display redirect div for 5 seconds and then redirects to the MainPage View.
Below is the method that is invoked on form submit. In this method, I, probably, need to have some kind of logic when my withRedirect flag is true. Currently, I'm just redirecting to MainPage, but I need to show Redirection Success message for 5 seconds.
[HttpPost]
public ActionResult Index(ChangePasswordModel model, string returnUrl*/)
{
ViewData["PasswordChanged"] = false;
bool withRedirect = Convert.ToBoolean(Session["WithRedirect"].ToString());
if (ModelState.IsValid)
{
string currentPassword = model.CurrentPassword;
string newPassword = model.NewPassword;
string confirmPassword = model.ConfirmPassword;
if (ChangePasswordModel.IsPasswordValid(newPassword))
{
try
{
ChangePasswordModel cpm = ChangePasswordModel.ChangePassword(model);
if (cpm.SuccessMessage.Length > 0)
{
ViewData["PasswordChanged"] = true;
ViewBag.Message = cpm.SuccessMessage;
if (withRedirect)
{
return Redirect(returnUrl ?? Url.Action("Index", "MainPage"));
}
}
else
{
ModelState.AddModelError("", cpm.FailMessage);
}
}
catch(Exception error)
{
ModelState.AddModelError("", error.Message);
}
}
else
{
ModelState.AddModelError("", "New password does not meet minimum requirements");
}
}
if (withRedirect)
{
return View("ForceChangePassword");
}
else
{
return View("ChangePassword");
}
}
How can I do something like that in MVC
In the Controller, Redirect to the View that renders the Partial View:
if (withRedirect)
{
return View("ViewA");
}
and in the View A, when displaying the "Redirect" message we can do it by either
1.
<div style="margin-top:20px;">
<div style="color:green;">
#ViewBag.Message
</div>
<div>
Please wait while you are redirected...
<script>
window.setTimeout(function () {
location.href = "MainPage";
}, 5000);
</script>
</div>
</div>
<div style="margin-top:20px;">
<meta http-equiv="refresh" content="5;url=MainPage">
<div style="color:green;">
#ViewBag.Message
</div>
<div>
Please wait while you are redirected...
</div>
</div>

MVC redirect to error page doesn't display message

In MVC I am trying to redirect a message to an Error page when it occurs. The Error Page will open but I get no error message.
This is the method that initiates the process.
[HttpPost]
public ActionResult SaveSurvey(vmFollowUpSurvey model)
{
var result = surveyBL.postSurveyResults(model);
if (result != "Record Saved")
{
ModelState.AddModelError(string.Empty, "Survey not saved");
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Error");
return Json(new { Url = redirectUrl });
}
else
{
ModelState.AddModelError(string.Empty, "Survey completed");
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Login");
return Json(new { Url = redirectUrl });
}
}
My ErrorController then has a method of
public ActionResult Index()
{
return View();
}
And my View displays as this
<h2>Survey Information Page</h2>
<div>
#using (Html.BeginForm("Index", "Error"))
{
<div class="container">
<div class="row">
#Html.ValidationSummary(false, "", new { #class = "text-info" })
</div>
</div>
}
</div>
So what did I not do to get this to display?
Your ErrorController.Index() method has no knowledge of the model being used, so adding the message to ModelState will mean your error page doesn't have access to it. If you're going to be redirecting to a different view, the proper way to handle this would be to put the error inside the Session.
if (result != "Record Saved")
{
Session["Error"] = "Survey not saved";
...
}
Then inside your Error view, you can do something like this:
<h2>Survey Information Page</h2>
<div>
#using (Html.BeginForm("Index", "Error"))
{
<div class="container">
<div class="row">
<span class="error-message">#Session["Error"]</span>
</div>
</div>
}
</div>
[HttpPost]
public ActionResult SaveSurvey(vmFollowUpSurvey model)
{
var result = surveyBL.postSurveyResults(model);
if (result != "Record Saved")
{
return RedirectToAction("Index", "Error", new { ErrorMessage= "Survey not saved"} );
}
else
{
ModelState.AddModelError(string.Empty, "Survey completed");
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Login");
return Json(new { Url = redirectUrl });
}
}
--- ErrorModel Class
namespace WebApplication3.Models
{
public class ErrorModel
{
public string ErrorMessage { get; set; }
}
}
--- Error Index.html code
#model WebApplication3.Models.ErrorModel
<h2>Survey Information Page</h2>
<div>
#using (Html.BeginForm("Index", "Error"))
{
<div class="container">
<div class="row">
#Html.ValidationSummary(false, Model.ErrorMessage , new { #class = "text-info" })
</div>
</div>
}
</div>

MVC controller.redirect doesn't redirect

I'm passing a string to Redirect but the controller is not sending the browser to the appropriate location.
The string is: "/Admin/SystemSecurity/_PermissionDetail/1"
The code is:
public ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
// Code get's here, but seems to go to /Submission/Index
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Submission");
}
In this case, the method that calls RedirectToLocal is _Login in the SubmissionController:
[ChildActionOnly]
public ActionResult _Login(string returnUrl)
{
if (Request.Cookies["UserName"] != null && !string.IsNullOrEmpty(Request.Cookies["UserName"].Value))
{
var loginModel = new Login { Email = Request.Cookies["UserName"].Value, ReturnUrl = returnUrl};
return PartialView(loginModel);
}
return PartialView();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> _Login(Login model, string returnUrl)
{
var isLoggedIn = UserLogin(model.Email, model.Password);
if (!isLoggedIn)
{
TempData["ErrorMessage"] = "Invalid email address or password.";
return RedirectToAction("Index", new { returnUrl = returnUrl });
}
// I make the call here, the values is correct here.
return RedirectToLocal(returnUrl);
}
Here's the Index method, also in SubmissionController:
public ActionResult Index(string message, string returnUrl)
{
IsAuthenticated();
if (!string.IsNullOrEmpty(message) )
AddMessage(message);
if (!string.IsNullOrEmpty((string)TempData["ErrorMessage"]))
{
AddError((string)TempData["ErrorMessage"]);
}
ViewBag.ReturnUrl = returnUrl;
return View();
}
After the POST _Login RedirectToLocal, the main Index method gets called again. Not sure who/what calls it. Probably something simple I'm missing.
For clarification I'm posting more of my View data here:
/Submission/Index:
#{
Layout = "~/Views/Shared/_Home.cshtml";
}
<div>
<p>...</p>
</div>
/Shared/_Home
#using PublicationSystem.ViewModels
#{
ViewBag.Title = "_Home";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container-fluid home-banner">
<!--Content from Index Page -------------------------------------->
<div class="clearfix"></div>
<div class="container">
<div class="row">
<div class="col-sm-4 col-md-3 col-lg-3">
<div class="left-side-blue">
...
</div>
</div>
<div class="col-sm-8 col-md-9 col-lg-9">
#{ Html.RenderPartial("_ErrorMessages"); }
#if (!ViewBag.IsAuthenticated)
{
Html.RenderAction("_Login", new { returnUrl = ViewBag.ReturnUrl });
}
else
{
<div class="hp-nav-boxes">...</div>
}
</div>
</div>
</div>
...
</div>
/Shared/_Login:
#model PublicationSystem.ViewModels.Login
<div class="login-box">
<div class="row">
#using (Html.BeginForm("_Login", "Submission", new { returnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "col-sm-6 col-md-4 col-lg-4 pull-right custm-login ipadsm4" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", #placeholder = "Email" })
#Html.ValidationMessageFor(m => m.Email, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.PasswordFor(m => m.Password, new { #class = "form-control", #placeholder = "Password" })
#Html.ValidationMessageFor(m => m.Password, "", new {#class = "text-danger"})
</div>
<button type="submit" class="btn btn-default pull-right">
Login <span aria-hidden="true" class="glyphicon glyphicon-play"></span>
</button>
<div class="clearfix"></div>
}
</div>
The login logic works and the user can get logged in. It's just this redirect that's messing up.
You're calling _Login a partial, but partials don't have associated actions. It might be a child action, but you can't post to child actions. As result, _Login is just a standard action, and unless you post to it directly via something like:
#using (Html.BeginForm("_Login"))
{
...
}
And then submit that form on the resulting page, the action will never be hit.
Assuming you're actually doing it that way already, and just confused about the terminology, then the next place to look is at the inconsistency in return URL variables. Your action accepts returnUrl as a param, but you're only using that if the user is not logged in, where you redirect to Index with that return URL. However, if the user is logged in, then you're calling RedirectToLocal with model.ReturnUrl instead.

Two strongly types partial views in one razor view

I am using Asp.Net identity logic module for authentication process. I am using this theme for login and signup and external logins all in one view.
Here is my Login.cshtml view that contain social login, register and login partials
#using Helping.ViewModels
#{
ViewBag.Title = "Log in";
}
<div class="container">
<div class="row">
<br />
<br />
<div class="col-lg-4">
<div>
<section id="socialLoginForm">
#Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl })
</section>
</div>
</div>
<div class="col-lg-4">
<h2><b>Sign Up</b></h2>
<hr />
#Html.Partial("Register")
</div>
<div class="col-lg-4">
<h2><b>Log In</b></h2>
<hr />
#Html.Partial("LocalLogin")
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
LocalLogin and Register are the strongly typed partial views.Problem is that when I try to Login with a user that doesnot exist it returns the model , here is the action
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account-Resend");
ViewBag.errorMessage = "You must have a confirmed email to log on.";
return View("Error");
}
else
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
It return following error
The model item passed into the dictionary is of type 'Helping.ViewModels.LoginViewModel', but this dictionary requires a model item of type 'Helping.ViewModels.RegisterViewModel'.
My Register view expects RegisterViewModel and My LocalLogin expects LoginViewModel
#using Helping.ViewModels
#model LoginViewModel
#model HelpingHands.ViewModels.RegisterViewModel
How to provide both the models with one view need help ?
You need to combine both your LoginViewModel and RegisterViewModel into one model (ViewModel).
Like..
public class LoginRegisterModel
{
public LoginViewModel LoginModel {get;set;}
public RegisterViewModel RegisterModel {get;set;}
}
Then you can pass this viewModel to your view..
#model Helping.ViewModels.LoginRegisterModel
Which says this view will be using the class LoginRegisterModel as the model..
And inside the view for your two partial views you can use..
Html.Partial("LocalLogin", Model.LoginModel)
Html.Partial("Register", Model.RegisterModel)
The error your getting is because you are not passing any model to your Register view and by default the model passed to your main view is carried forward to the call of partial Register view.
** I m on mobile, forgive me for bad formatting. And if anyone can format the code section its greatly appreciated**

Resources