return partialview after httppost asp.net mvc - asp.net-mvc

I am creating a web app in asp.net mvc
I have a partial view to reset password which opens inside bootstrap modal,
now on HttpPost I have a if condition which looks like below
if (string.IsNullOrEmpty(model.NewPassword))
{
TempData["PMessage"] = CustomHelper.Translate("Please Enter new Password");
return PartialView(model);
}
but my main url is changing to this partial view like below
http://localhost:8080/User/ResetPassword
here ResetPassword is my partialview name
my partialView looks like below
#(Html.BeginForm("ResetPassword", "User", FormMethod.Post))
{
<div class="modal-dialog modal-sm">
<!-- Modal data-->
</div>
}
my full post method
[HttpPost]
public ActionResult ResetPassword(ResetPasswordModel model)
{
if (string.IsNullOrEmpty(model.NewPassword))
{
TempData["PMessage"] = "Please Enter new Password";
return PartialView(model);
}
//if success
return RedirectToAction("Index");
}
how can I prevent this, I just want to load modal and not whole page,
what can be the fixes here?
or Should I go for client side validation?
Page flow in detail
this is how my page looks
if the user clicks on reset password, the below bootstrap modal appears
without entering any data if user clicks on OK, post method has been called and the page is being redirected to resetpassword.cshtml as I am returning like below
return PartialView(model);
what I need to do if I only want to refresh modal/partial view on validation on controller

You are making normal HTTP request it's used to handle regular browser calls (like form submits) and return full HTML pages to client.
In your case you have to make ajax request to handle ResetPassword post method to avoid redirect.
<!-- modal placeholder-->
<div id='myModal' class='modal fade in'>
<div class="modal-dialog">
<div class="modal-content">
<div id='myModalContent'></div>
</div>
</div>
</div>
this url return your reset form and load it into a modalcontent
<a href="#Url.Action("Reset", "Account", new { class = "resetpassword" })" ></a>
$(function () {
$(document).on("click", "a.resetpassword", function (e) {
$('#myModalContent').load(this.href, function () {
$('#myModal').modal({
/*backdrop: 'static',*/
keyboard: true
}, 'show');
bindForm(this);
});
return false;
});
});
function bindForm(dialog) {
$('form', dialog).submit(function (e) {
e.preventDefault();
if ($('#resetFormId').valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$('#myModal').modal('hide');
} else {
$('#myModalContent').html(result);
bindForm(dialog);
}
}
});
}
return false;
});
}

Related

Controller code gets called twice

I have an MVC view which will have menu and detail sections. As items are clicked on the menu, I would like the detail section to get updated. The menu and detail would be PartialViews.
My main view is layed out like this (so far):
#model WorkflowData.ProjectWorkflow
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="form-horizontal">
<h4>Project Workflow</h4>
<hr />
<div>
#{Html.RenderPartial(
"_WorkflowSteps",
Model.ProjectWorkflowSteps.ToList());
}
</div>
<div id="StepDetail"></div>
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section scripts{
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script>
$(function () {
$('.workflow-step').on('click', function (e) {
$.get($(this).prop('href'), function (response) {
$('#StepDetail').html(response)
});
});
});
</script>
}
The '_WorkflowSteps' partial view renders links using this:
#Html.ActionLink(
item.StepName,
"Step",
new { id = item.ProjectworkflowPages.FirstOrDefault().ProjectWorkflowPageId },
new { #class = "workflow-step" });
My controller action for Step is:
public ActionResult Step(int id)
{
if (id == null)
return RedirectToAction("Index");
using (var _db = new MarkTestDbEntities())
{
var stepPage = (from s in _db.ProjectworkflowPages
where s.ProjectWorkflowPageId == id
select s).FirstOrDefault();
var projectModel = new Project
{
ProjectWorkflowId = stepPage.ProjectWorkflowStep.ProjectWorkflowId
};
return PartialView(string.Format("../{0}/{1}",stepPage.Controller, stepPage.CreateAction)
, projectModel);
}
return View();
}
What is happening now is I see the div get populated with the partial view, then the page refreshes with just the partial view from Step. Debugging I see that the Step action is actually called twice, but when I look at the rendered source, I don't see why. Any thoughts?
Your elements with class="workflow-step" are links which make a GET call to your Step() method. You are handling the .click() event of those elements and making a ajax call, but your not cancelling the default redirect so its doing both, the $.get() followed by the redirect. You need to cancel the default action by including return false; in the script
$('.workflow-step').on('click', function (e) {
$.get($(this).prop('href'), function (response) {
$('#StepDetail').html(response)
});
return false; // add this
});

MVC 5 partial view async postback

I have a sort of Master-Detail Edit form and I'm trying to follow this post: Using Ajax... to get the partial view to postback.
My Edit form has a partial view that has a list of sub items, and another partial create view in it to add new items. I'd like the partial create view to post back and update the list without refreshing the whole page if possible.
Here's what I have so far:
MyController.cs -
public ActionResult Edit(int? id)
{
//...
ViewBag.CustomFormId = id;
using (var _db = new MkpContext())
{
//...
return View(profileEdit);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomForm editForm)
{
//...
if (!ModelState.IsValid) return View(editForm);
using (var _db = new MkpContext())
{
var form = _db.CustomForms.Find(editForm.CustomFormId);
//...
_db.Entry(form).State = EntityState.Modified;
_db.SaveChanges(User.ProfileId);
return RedirectToAction("Index");
}
}
public ActionResult _CustomFieldList(int id)
{
ViewBag.CustomFormId = id;
using (var _db = new MkpContext())
{
var formCustomFields = (from cf in _db.CustomFields
where cf.CustomFormId == id
select cf);
return PartialView(formCustomFields.ToList());
}
}
// Nested in _CustomFieldList
public ActionResult _CustomFieldCreate(int id)
{
var newField = new CustomField
{
CustomFormId = id
};
return PartialView(newField);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _CustomFieldCreate(CustomField addField)
{
ViewBag.CustomFormId = addField.CustomFormId;
if (ModelState.IsValid)
{
using (var _db = new MkpContext())
{
_db.CustomFields.Add(addField);
_db.SaveChanges();
}
var newField = new CustomField
{
CustomFormId = addField.CustomFormId
};
return PartialView(newField); // Probably need to change this somehow
}
return PartialView(addField);
}
And the views:
Edit.cshtml -
#model PublicationSystem.Model.CustomForm
#{
ViewBag.Title = "Edit Custom Form";
Layout = "~/Views/Shared/_LayoutSmBanner.cshtml";
}
<div class="form-horizontal">
<div class="row">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#* Fields for this form *#
}
<div id="CustomFields" class="col-md-6">
#Html.Action("_CustomFieldCreate", new { id = ViewBag.CustomFormId })
</div>
</div>
</div>
<script>
$(function () {
$("#createFieldForm").on("submit", function (e) {
e.preventDefault(); //This prevent the regular form submit
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
$("#CustomFields").html(result);
}
});
return false;
});
});
</script>
_CustomFieldCreate.cshtml -
#model PublicationSystem.Model.CustomField
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div id="result"></div>
<div class="form-horizontal">
<h4>CustomField</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model =>model.CustomFormId)
<div class="row">
#* Fields for the form *#
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div id="customFieldList">
#Html.Action("_CustomFieldList", new { id = ViewBag.CustomFormId })
</div>
_CustomFieldList.cshtml
#model System.Collections.Generic.IEnumerable<PublicationSystem.Model.CustomField>
<table class="table">
#* List table code *#
</table>
Edit: I rewrote the pages so that the list is part of the create partial view. What happens now is, if you enter data for _CustomFieldCreate and press submit, the first time, it refreshes just that view (including the nested list view). However the second time, it redirects to the view, probably because the first refresh didn't rebind the javascript to the submit button. Also, the Create view doesn't clear out the fields, but persists the originally entered data.
You will need a form in your partial view whose submit action binds to a javascript function that posts to your controller.
For example if your form id is MyForm:
$('#MyForm').on('submit', function (e) {
e.preventDefault(); //This prevent the regular form submit
$.ajax({
url: $(this).action, // This will submit the post to whatever action your form goes to
type: "POST", // This tells it that it is a post
data: $(this).serialize(), // This sends the data in the form to the controller
success: function (data) {
// do some javascript on success
},
error: function (xhr, ajaxOptions, thrownError) {
// do some javascript on error
}
});
});
This javascript overrides the default form submit and does an ajax post to your controller and then returns with success or error where you can do anything you want.
Here is some jquery ajax documentation:
http://api.jquery.com/jquery.ajax/
You should look into using AJAX. That should accomplish what I think you are describing. You'll want to create a javascript function that handles the submit event on the form, then post the form data to some create action in your MVC app using AJAX. If you are using jQuery, the library makes it pretty simple.
http://api.jquery.com/jquery.ajax/

Can you just update a partial view instead of full page post?

Is there a way to submit a partial view form in asp.net mvc without reloading the parent page, but reloading the partial view only to its new state? Similar to how knockout.js updates using data-bind.
My data table renders with a variable number of columns/names so I don't think knockout.js is an option for this one, so I am trying to use a partial view instead.
Not without jQuery.
What you would have to do is put your Partial in a div, something like:
<div id="partial">
#Html.Partial("YourPartial")
</div>
Then, to update (for example clicking a button with the id button), you could do:
$("#button").click(function () {
$.ajax({
url: "YourController/GetData",
type: "get",
data: $("form").serialize(), //if you need to post Model data, use this
success: function (result) {
$("#partial").html(result);
}
});
})
Then your action would look something like:
public ActionResult GetData(YourModel model) //that's if you need the model
{
//do whatever
return View(model);
}
Actually, if your Partial has a child action method, you can post (or even use an anchor link) directly to the child action and get an Ajax-like affect. We do this in several Views.
The syntax is
#Html.Action("MyPartial")
The Child Action is
public ActionResult MyPartial()
{
return PartialView(Model);
}
If your form posts to the child action
#using (Html.BeginForm("MyPartial"))
{
    ...
}
The Partial View will be updated with the partial view returned from the child action.
Jquery is still a legitimate way to update a partial. But technically, the answer to your question is YES.
As normal what I find when looking for things like this is people give too limited information so I will attempt to help here. The key is to set up a div with an ID you can append the return html to. Also when hitting your controller make sure it returns the partial. There are some potential problems with this method but on a good day it should work.
<div id="CategoryList" class="widget">
#{
Html.RenderPartial("WidgetCategories.cshtml");
}
</div>
function DeleteCategory(CategoryID) {
$.get('/Dashboard/DeleteWidgetCategory?CategoryID=' + CategoryID,
function (data) {
if (data == "No") {
alert('The Category has report widgets assigned to it and cannot be deleted.');
}
else {
$('#CategoryList').html(data);
}
}
);
}
[HttpGet("DeleteWidgetCategory")]
[HttpPost("DeleteWidgetCategory")]
public IActionResult DeleteWidgetCategory(string CategoryID)
{
string Deleted = CategoryModel.DeleteCategory(CategoryID);
if (Deleted == "Yes")
{
return PartialView("WidgetCategories");
}
else
{
return this.Json("No");
}
}
I would use the Ajax Form helper for such scenarios using a partial view and #html.RenderPartial("partialName")
partial helpers
In your Main View
<div id=SearchResult>
#Html.Partial("_NameOfPartialView", Model)
</div>
<input type="button" id="btnSubmit" value="Submit">
In your Javascript file
$('#btnSubmit').click(function () {
GetData(Id);
});
function GetData(Id){
$.ajax({
url: "/Home/GetEmployee/",
type: "get",
data: { Id:Id },
success: function (result) {
$('#SearchResult').html(result);
}
});
}
In your Home Controller
public ActionResult GetEmployee(int Id)
{
var employee= context.Employee.Where(x=> x.EmployeeId == Id)
return this.PartialView("_NameOfPartialView", employee);
}

mvc c# with jquery getjson not closing the modal popup but redirects to another page with json result

So I'm not sure what's happening here. I have this modal popup that loads a partial view from an action (this might be the problem??) . The partial view loads perfectly and processes fine but once the post ends and should return a json, instead of the modal just closing and then posting the results it redirects me to another page that shows the json results (not the partial view). I'm not entirely sure if the way i'm approaching this is correct. I just need to close the dialog after the action was successfully processed and then return a message if it has either saved the transaction or throw an error.
Any advice is appreciated. thanks!!!
<script type="text/javascript">
$(function () {
$('#modal-link').click(function () {
var href = this.href;
$('#load-modal-dialog').dialog({
modal: true,
open: function (event, ui) {
$(this).load(href, function (result) {
$('#new-registration').submit(function () {
$.getJSON(href, function (data) {
if (data.success == true) {
$('#messages').html('woo!');
} else {
$('#messages').html('dafuq');
}
this.dialog('close');
});
});
});
}
});
return false;
});
});
</script>
my partial view that gets loaded on the popup
<% using (Html.BeginForm("New", "Registration", FormMethod.Post, new { id = "new-registration" })){ %>
<h2>Register Participant:</h2>
<div class="">
<%: Html.ValidationSummary(null, new { #class = "" })%>
<div class="">
<div class="">Email Address:</div>
<div class="">
<%: Html.TextBox("Email", null, new { #class = "" })%>
</div>
</div>
<button type="submit" value="Submit">Register</button>
</div>
<% } %>
the action
public ActionResult New(){
return PartialView(context.Contest.FirstOrDefault(e => e.Id == 1));
}
[HttpPost]
public ActionResult New(FormCollection formCollection)
{
string email = formCollection["Email"].ToString();
try
{
if (email == "")
throw new Exception("Please provide an email address.");
Registration registration = new Registration
{
ContestId = 1,
Email = email
};
context.Registration.Add(registration);
context.SaveChanges();
return Json(new { success = "true", message = "User succesfully registered to Contest." });
}
catch (Exception ex)
{
//throw ex;
return Json(new { success = "false", message = ex.Message });
}
}
You need to prevent the default action of the link(Opening a new window).Add these lines to your code,
$('#modal-link').click(function (event) {
//....All content..
event.preventDefault();// this will stop the opening new page
event.stopPropergation();
return false;
});

ASP.NET MVC Refresh usercontrols

ASP.NET MVC
I have one page Index.aspx where I'm loading two usercontrols into divs. This is working fine. For the moment the usercontrols just shows data and thats working fine. But now I want to add a delete function in the usercontrols and then refresh the div in the Index.aspx page. Is this possible?
Index.aspx
<!-- Panel One -->
<div id="panel1">
<img src="/Content/ajax-loader.gif" alt="Loading..." />
</div>
<script type="text/javascript">
$('#panel1').load('../Reports/ReportOne')
</script>
<!-- Panel Two -->
<div id="panel2">
<img src="/Content/ajax-loader.gif" alt="Loading..." />
</div>
<script type="text/javascript">
$('#panel2').load('../Reports/ReportTwo')
</script>
ReportOne.ascx and ReportTwo
Just listing some data with a foreach. Here I want to add a deletebutton for each item in the lists.
Make your "delete" action into something like this:
[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult Delete(int id) {
try {
// do what ever here in deleting the record etc
// ...
return null;
} catch (Exception ex) {
TempData[TempDataKeys.ErrorMessage] = "Error in deleting: " + ex.Message;
return RedirectToAction("List");
}
}
In you ascx/aspx, create a jQuery method to wrap your ajax call to the controller:
function deleteRecord(recordId) {
if (confirm("Are you sure that you want to delete this record?")) {
var token = $("input[name='__RequestVerificationToken']")[0].value;
url = '<%= Url.Action("Delete", "MyController") %>';
$.post(
url,
{ id: recordId, __RequestVerificationToken: token },
function(data) {
if (!data == "") {
// success - reload/refresh panel control
$('#panel1').load('../Reports/ReportOne');
} else {
// failed - handle error
}
}
);
}
}
You will need to put your AntiForgeryToken appropriately so the script can access it - you only need 1 for the whole page. Your delete link should then call to the javascript, instead of to the action in the controller directly:
Delete
When the user clicks on the delete button inside the user control you could invoke an action that will delete the necessary information from the database and return a partial view refreshing the control. So put a delete link inside the control:
<%= Html.ActionLink("Delete", "DeleteReportOne", null, new { id = "deleteReportOne" }) %>
and then inside the main page register the click callback for this link:
$(function() {
$('#deleteReportOne').click(function() {
$('#panel1').load(this.href);
});
});
You may use JQuery UI tabs to add and remove the content from the page
JQuery UI Manipulate tabs
JQuery Tabs and ASP.NET MVC Partial Views
you need to modify your user controls

Resources