How do I redirect from an MVC Post Action back to the bootstrap popup modal partial view where the post came from? - asp.net-mvc

How do I redirect from an MVC Post Action back to the bootstrap popup modal partial view where the post came from?
Here is the PartialView sitting in the Bootstrap modal popup on the page.
It has a div with a validation taghelper waiting for any model errors.
#model CreateRoleViewModel
<div class="panel panel-primary partialModalFormDivs">
#Html.Partial("_ModalHeader",
new ModalHeader
{
Heading = "ADD ROLE",
glyphiconClass = "glyphicon glyphicon-random"
}
)
<div class="panel-body">
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="CreateRole" method="post">
<div class="form-group">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form form-control" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</form>
</div>
</div>
It posts to this action:
[HttpPost]
public async Task<IActionResult> CreateRole(CreateRoleViewModel createRoleViewModel)
{
if (ModelState.IsValid)
{
IdentityRole role = new IdentityRole(createRoleViewModel.RoleName);
IdentityResult result
= await _roleManager.CreateAsync(role);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
return View(createRoleViewModel);
}
I can return a PartialView like this at the end:
return View("_CreateRole", createRoleViewModel);
But then the whole page is cleared and this partial is returned with no layout file.
How can I return the results back to the modal popup window.
I understand the problem and the current behavior. But has anyone else solved this?

I think what you want to do is an ajax post and then just return a partial view and replace the form. The form should be inside a container div with an id that is used to replace its contents with the ajax post result. To do this you need to include the jquery unobtrusive ajax script which will auto wire the ajax based on the data-* attributes on the form as shown below
<div class="panel-body">
<div asp-validation-summary="All" class="text-danger"></div>
<div id="resultcontainer">
<form asp-action="CreateRole" method="post"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#resultcontainer"
>
<div class="form-group">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form form-control" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</form>
</div>
</div>
and don't forget to return a partial view
return PartialView(createRoleViewModel);

Related

Edit action in controller not updating

When I edit an item and return to the index view the item doesn't show what I updated it to.
I think I know what the problem is but not sure how to fix it. In my service class I have a CreateEditItem method and when I step thru the code it hits the if condition <=0. So it acts like there is an id of 0 when I click the submit button to submit my update. I'm not sure what to do to fix this. Do I need to have a separate method for Edit? And if so what should that look like?
public bool CreateEditItem(Item item)
{
if (item.ItemId <= 0)
{
var maxId = _mockList.Max(p => p.ItemId);
item.ItemId = maxId + 1;
_mockList.Add(item);
return true;
}
var itemToEdit = _mockList.FirstOrDefault(p => p.ItemId ==
item.ItemId);
itemToEdit = item;
return true;
}
Action in Controller
[HttpPost]
public IActionResult EditItem(Item itemToEdit)
{
_itemService.CreateEditItem(itemToEdit);
return RedirectToAction(nameof(Index), new { id =
itemToEdit.ItemId });
}
View:
<div class="row">
<form asp-action="EditItem">
<div asp-validation-summary="ModelOnly" class="text-
danger"></div>
<div class="container form-group">
<div class="row">
<div class="col-md-2">As Of : <label
for="AsOf" /></div>
<div class="col-md-4"><input id="AsOf"
value="#Model.ItemToEdit.AsOf" name="AsOf" type="date" /></div>
</div>
<br />
<div class="row">
<div class="col-md-2">Title Summary : <label
for="TitleSummary" /></div>
<div class="col-md-2"><input id="TitleSummary"
value="#Model.ItemToEdit.Title" name="Title" type="text" /></div>
</div>
<br />
<br />
<div class="row">
<div class="col-md-2"><input type="submit"
value="Submit" class="btn btn-primary" /></div>
</div>
</div>
</form>
</div>
I expect when I click the submit button to submit my update it will show the updated Title and/or AsOf date.
change your method from HTTPut to HttpPost
it will work.

Button Submit in MVC is not working as expected

I have a submit button in index.cshtml page and when i click that button i need to go in another ActionResult server method.But it's not working.(not hitting to the server side method)
Html
#model IEnumerable<AAB.Domain.Items>
<!-- Featured Products -->
<div class="card-deck card-deck-product mt-3 mb-2 mb-sm-0">
#foreach (var item in Model)
{
<div class="card card-product" id="#item.ItemId">
<div class="card-body">
<button class="wishlist atw-demo " title="Added to wishlist"><i data-feather="heart"></i></button>
<img class="card-img-top" src="#item.ImageUrl" alt="Card image cap">
#item.ItemName
<div class="price"><span class="h5">Rs:#item.ItemPrice</span></div>
</div>
<div class="card-footer">
<input type="submit" class="btn btn-sm" id="#item.ItemId" value="Add to Cart" href="#Url.Action("AddNewItems","Home",new { ItemId=item.ItemId})"/>
</div>
</div>
}
</div>
Server side
[HttpPost]
public ActionResult AddNewItems(int ItemId)
{
// Some code here.
return PartialView("_PopCart", ItemId);
}
Surround your button with a tag.
<a href="#Url.Action("AddNewItems","Home",new { ItemId=item.ItemId})">
<input type="submit" class="btn btn-sm" id="#item.ItemId" value="Add to Cart" />
</a>

How can I return text to my current mvc view?

I have a login page within an ASP.NET Core App with a pop up to send a password reset email to the users email (Just using Identity):
<div class="login-body">
<div class="container">
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" class="form-signin">
<h2 class="form-signin-heading">#Localizer["Sign In"]</h2>
<div class="login-wrap">
<div class="user-login-info">
<input asp-for="Email" type="email" class="form-control" placeholder="#Localizer["Email"]" autofocus/>
<span asp-validation-for="Email" class="text-danger"></span>
<input asp-for="Password" type="password" class="form-control" placeholder="#Localizer["Password"]"/>
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<label class="checkbox">
<input asp-for="RememberMe"/> Remember me
<span class="pull-right">
<a data-toggle="modal" href="#forgotPassModal">Reset Password</a>
</span>
</label>
<button class="btn btn-lg btn-login btn-block" type="submit">#Localizer["Sign In"]</button>
<div class="registration">
#Localizer["No Account"]
<a asp-area="" asp-controller="Account" asp-action="Register">#Localizer["Create Account"]</a>
</div>
</div>
<!-- Modal -->
<div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="forgotPassModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Reset Password</h4>
</div>
<div class="modal-body">
<p>Enter your e-mail address below to reset your password.</p>
<input type="text" name="email" placeholder="Email" autocomplete="off" class="form-control placeholder-no-fix">
</div>
<div class="modal-footer">
<button data-dismiss="modal" class="btn btn-default" type="button">Cancel</button>
<button class="btn btn-success" asp-controller="Account" asp-action="ForgotPassword" method="post">Submit</button>
#*<input type="button" class="btn btn-success" asp-controller="Account" asp-action="ForgotPassword" formmethod="post">Submit<input>*#
</div>
</div>
</div>
</div>
<!-- modal -->
</form>
</div>
When I input the email address it does the right thing, sends an email with a code, but it redirects me to a separate view stating to go check your emails.
Is it possible to just return a message either to the popup window or login page saying the same thing?
This is the ForgotPassword Action:
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null || !(await UserManager.IsEmailConfirmedAsync(user)))
{
return View("ForgotPasswordConfirmation");
}
var code = await UserManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action(nameof(ResetPassword), "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Reset Password",
$"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
return View("ForgotPasswordConfirmation");
}
return View(model);
}
What you can use is TempData. TempData can hold data for one more additional request and only for one additional request. So you can store this information in the TempData. It is meant for things like your use case. It could look something like this.
public IActionResult Login()
{
var loginModel = new LoginModel();
loginModel.ForgotPassWordModel = (ForgotPassWordModel) TempData["ForgotPassword"];
return View(loginModel);
}
public IActionResult ForgotPassword()
{
if (valid)
{
TempData["ForgotPassword"] = new ForgotPassWordModel() {callbackUrl = "Go to this"};
return RedirectToAction("Login");
}
return View();
}
Here is my example LoginModel and my ForgottonPasswordModel. Ofcourse, yours will be more complicated.
public class ForgotPassWordModel
{
public string callbackUrl;
}
public class LoginModel
{
public ForgotPassWordModel ForgotPassWordModel { get; set; }
}
When someone makes a request to ForgotPassword, if it is valid, store the result in TempData and Redirect back to Login. Now you can read the TempData["ForgotPassword"] that you just set in the previous request. In my example, I put the data in my LoginModel. If there is no tempData, it would be null. Now in your view you can check for this ForgotPassword property.
#if (Model.ForgotPassWordModel != null)
{
// Show message/modal
}
The great thing about TempData is that when you set data, it is only held for one more additional request so it works for situations like these.

Bad Request MVC HttpPost

I have the following cshtml file.
#model Models.AuthorizeUser
#{
ViewBag.Title = "Authorize";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container">
<div class="card card-container">
<img class="profile-img-card" src="~/Content/images/rblogo_reverse-pms348_000.gif" />
<p> </p>
<form method="POST">
<p>Hello, #Model.Name</p>
<p>A third party application want to do the following on your behalf:</p>
<ul>
#foreach (var scope in Model.Scopes)
{
<li>#scope.ScopeDescription</li>
}
</ul>
<div class ="row">
<div class="col-md-4">
<button class="btn btn-block btn-primary btn-signin" name="submit" type="submit" value="authorize">Grant</button>
</div>
<div class="col-md-8">
<button class="btn btn-block btn-primary btn-signin btn-small-text" name="submit" type="submit" value="logout">Sign in as different user</button>
</div>
</div>
</form>
</div>
</div>
I have my controller file as follows:
public class OAuthController : Controller
{
[HttpGet]
public ActionResult Authorize()
{
logger.Trace("Authorize method entered");
AuthorizeUser authorizeUser;
......
return View(authorizeUser);
}
[HttpPost]
public ActionResult Authorize(AuthorizeUser authorizeUser, string submit)
{
logger.Trace("Authorize with object");
if (Response.StatusCode != 200)
{
logger.Trace("status code " + Response.StatusCode);
logger.Trace("status description " + Response.StatusDescription);
return View("AuthorizeError");
}
..............
}
When the form is displayed, the info is displayed correctly. After I click Grant button, I got Response.StatusCode == 400. Both authorizeUser and submit are null. I am expecting StatuCode == 200 with values of authrizeUser and submit.
Have you tried using Html.BeginForm()?
Instead of using <form method="POST"> you could use Html.BeginForm("Action", "Controller")

getting null value for HttpPostedFileBase in mvc controller

I want to give user the option to change their profile picture.On hitting the save button my controller action is hit but I get null value for HttpPostedFileBase.I am uploading files first time in mvc so not able to figure out where I am doing wrong and hence getting null value in controller.
controller
[AuthenticationRequired]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ChangeProfilePicture(HttpPostedFileBase imageData)
{
}
view
#using (Ajax.BeginForm("ChangeProfilePicture", "Account", new { enctype = "multipart/form-data" },new AjaxOptions { OnSuccess = "OnSuccess" }))
{
#Html.AntiForgeryToken()
<div class="modal-body" id="tilesDescription">
<div class="row">
<div class="col-md-12">
<div class="text-center">
<div class="fileUpload btn btn-primary">
<span>Select a photo from your computer</span>
<input id="uploadBtn" type="file" class="upload" name="imageData" accept="image/*" />
</div>
<div class="text-center">
<img id="imgprvw" alt="uploaded image preview" class="imgPreview hide" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-rounded btn-sm btn-tiles" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-rounded btn-sm btn-tiles disabled" id="btnProfilePic">Set as profile picture</button>
</div>
}
You cannot post your file using ajax like that, cause is not supported.
From my experience, the easiest way to get files posted using Ajax (if using jquery), is using :
http://malsup.com/jquery/form/

Resources