Display a modal popup div from controller - c#

Can please someone help me here?! Thank you!
I have a view that displays a list of products along with an "Add Product" button for each. I am calling the CreateNewProduct method for each "Add Product" click to find the status of the product. Depending on the status, either I need to stay on the same view or I need to call a modal popup. I am able to do this by creating a modal popup in a different view. But I want to call the modal popup div (also pass the modal) from the same view where it displays a list of products. Is this possible?
public ActionResult CreateNewProduct(int productId)
{
var sharedProduct = _productTemplateService.GetSharedProducts(productId);
var _finalSharedProducts = (sharedProduct.Any(t => t.productId != productId));
if (_finalSharedProducts)
{
var sharedProdctTemplate = _productTemplateService.GetSharedProduct(productId);
return View("ModalView", new SharedModel
{
SharedProduct = sharedProdctTemplate
});
}
else
{
_productTemplateService.CreateNewProduct(productId);
return RedirectToAction("Details", "ProductTemplate");
}
}
Model View Code
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Shared Product</h4>
</div>
<div class="modal-body">
<div class="flex-row">
<div class="col-6">
<div class="d-flex flex-row">
<div class="p-2">Product ID</div>
<div class="p-2">Product Types</div>
<div class="p-2">Status</div>
</div>
#foreach (var productTemplate in Model.SharedProduct )
{
<div class="d-flex flex-row">
<div class="p-2">#productTemplate.ProductId</div>
<div class="p-2">#productTemplate.ProductType</div>
<div class="p-2">#productTemplate.StatusCode</div>
</div>
}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<p>
#Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ }) |
#Html.ActionLink("Back to List", "Index")
</p>
<script type="text/javascript">
$(document).ready(function () {
$('#myModal').modal('show');
});
</script>
UPDATE:
I made it working. This is what I did. At the end, I have mentioned issues I am facing.
Link, modal and script in my main view - Detail View (called from ProductTemplate Controller)
<td>Add New Product</td>
<div class="modal fade" id="mymodel" role="dialog" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Shared Products</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body" id="mymodelbody">
</div>
</div>
</div>
<script>
var loadModal = function (productId, customerId) {
$.ajax({
type: 'GET',
url: '/NewProductTemplate/CreateNewProduct',
cache: false,
data: {
productId: productId,
customerId: customerId
},
dataType: 'html',
success: function (data) {;
$("#mymodelbody").html(data);
$("#mymodel").modal("show");
}
});
}
</script>
NewProductTemplateController Code
public ActionResult CreateNewProduct(Guid productId, Guid customerId)
{
var sharedProduct = _productTemplateService.GetSharedProducts(productId);
var _finalSharedProducts = (sharedProduct.Any(t => t.productId != productId));
if (_finalSharedProducts)
{
var sharedProdctTemplate = _productTemplateService.GetSharedProduct(productId);
return PartialView("_shared", new SharedModel
{
SharedProduct = sharedProdctTemplate
});
}
else
{
_productTemplateService.CreateNewProduct(productId);
return RedirectToAction("Details", "ProductTemplate");
}
}
Partial view _shared.view code
#model SharedModel
#using (Html.BeginForm("ShareProduct", "NewProductTemplate", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="flex-row">
<div class="col-6">
<div class="d-flex flex-row">
<div class="p-2">Product ID</div>
<div class="p-2">Product Types</div>
<div class="p-2">Status</div>
</div>
#for (var i = 0; i < Model.SharedProducts.Count(); i++)
{
#Html.HiddenFor(model => model.SharedProducts.ElementAt(i).ProductId)
#Html.HiddenFor(model => model.SharedProducts.ElementAt(i).CustomerId)
#Html.HiddenFor(model => model.SharedProducts.ElementAt(i).ProductType)
#Html.HiddenFor(model => model.SharedProducts.ElementAt(i).StatusCode)
#Html.HiddenFor(model => model.SharedProducts.ElementAt(i).IsShared)
<div class="d-flex flex-row">
<div class="p-2">#Html.DisplayFor(model => model.SharedProducts.ElementAt(i).ProductId)</div>
<div class="p-2">#Html.DisplayFor(model => model.SharedProducts.ElementAt(i).ProductType)</div>
<div class="p-2">#Html.DisplayFor(model => model.SharedProducts.ElementAt(i).StatusCode)</div>
#if (Model.SharedProducts.ElementAt(i).StatusCode == VersionStatus.PUBLISHED)
{
<div class="p-2">#Html.EditorFor(m => m.SharedProducts.ElementAt(i).IsShared)</div>
}
</div>
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-sm btn-primary" />
<button type="button" class="btn btn-sm btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
PROBLEM:
1) When I save submit button in modal pop-up (partial view), it calls ShareProduct method from NewProductTemplate controller. For some reason, model SharedModel's SharedProducts property is null when it gets to controller code. Can you please help me here why it gets null?
public ActionResult ShareProduct (SharedModel shareModel)
{
//Access ShareProducts from shareModel
return RedirectToAction("Details", "ProductTemplate");
}
PROBLEM:
2) I want to load popup only if the product is shared, otherwise I just want to redirect to Detail view as mentioned in NewProductTemplate controller's CreateNewProduct method. Problem is that it loads Detail view also in popup if product is not shared since that's what my script is doing. Is there any way that I can check data in Success function before showing modal popup? If data/html contains Shared text, I would like to load the normal Detail view. I am just assuming. I tried to do so but with no success.
Detail method in ProductTemplate Controller
public ActionResult Details()
{
var productTemplate = _productTemplateService.GetAllProducts(User);
return View(new DetailsModel
{
ProductTemplate = productTemplate,
});
}

(This is for Bootstrap 3.3.7 Hopefully it's relevant for the version you're on)
I handle this by popping open the modal on the client side from my main view. The link that pops the modal contains the URL to the controller method that will render the actual contents (list of products, in your case). This controller method should return a partial view.
Modal in my main view:
<div class="modal fade name-of-my-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content"></div>
</div>
</div>
Link in my main view:
<a class="btn btn-default btn-xs" data-toggle="modal" data-target=".name-of-my-modal" role="button" href="/SomeController/SomeMethodThatReturnsPartialView/234">Show Modal</a>
My controller method for the partial view:
public ActionResult SomeMethodThatReturnsPartialView(int id)
{
var model = GetProducts();
return PartialView("_IndexPartial", model);
}
My partial view that will populate the actual modal contents:
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Title goes here</h4>
</div>
<form class="form-horizontal" id="SomeId" name="SomeName" role="form">
<div class="modal-body">
<div>Product 1</div>
<div>Product 2</div>
<div>Product 3</div>
<div>Product 4</div>
</div>
</form>
Also, if the contents of the modal change frequently, or are variable based upon the ID you pass to the partial controller method, then you'll want to clear the modal contents when closing it. From your main view:
$(document).on('hidden.bs.modal', '.modal', function (e) {
// Handles the event thrown when a modal is hidden
$(this).removeData('bs.modal');
$(this).find(".modal-content").empty();
});
Let me know if this helps, and whether anything needs to be clarified.

Problem 2 you could return a JSON result and put the HTML in a string as shown here:
https://www.codemag.com/article/1312081/Rendering-ASP.NET-MVC-Razor-Views-to-String
you could also set a boolean on the returned JSON for whether to redirect.
If it is a redirect do that in Javascript on the success using
window.location

Related

Why is my AJAX form posting mutliple times from my partial view in ASP.NET Core?

I am posting form data to my controller using AJAX, the form is located in a partial view which is called and displayed in a modal. When first submit the form to update my data it works fine, then if I post it again I notice in the console log that it posts the data twice, if I post it again, it posts three times, and so on. The only way to prevent that behavior is to refresh the page.
Here is the code for my partial view.
#model UserView
<div class="modal fade" id="edit-custom-view" tabindex="-1" role="dialog" aria-labelledby="edit-custom-view" aria-modal="true">
<div class="modal-dialog modal-dialog-scrollable modal-lg modal-notify modal-primary" role="document">
<div class="modal-content">
<form id="ModalFormEditCustomView" enctype="multipart/form-data">
<div class="modal-body">
<div class="row">
<input type="text" asp-for="Id" hidden readonly />
<div class="col">
<div class="md-form form-group">
<label asp-for="ViewName">View Name</label>
<input type="text" required class="form-control" asp-for="ViewName" />
</div>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="button" data-save="edit-view" class="btn btn-info waves-effect waves-light">Update</button>
<button type="button" class="btn btn-secondary waves-effect waves-light" data-dismiss="modal">Close</button>
</div><!--/modal-footer-->
</form>
</div>
</div>
</div>
My function that posts the data. Please note, placeholderElement is a div that is the modal window.
placeholderElement.on('click', '[data-save="edit-view"]', function (event) {
//Prevent the standard behaviour
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl , dataToSend).done(function (data) {
var newBody = $('.modal-body', data);
placeholderElement.find('.modal-body').replaceWith(newBody);
placeholderElement.find('.modal').modal('hide');
});
});
Here is my controller
[HttpPost]
public JsonResult EditCustomView(UserView model) {
... update code goes here
return Json(model);
}
This is the button that opens the modal with the form in it.
<button data-view-id='#=Id#' onclick='editViewModal(this, event)' data-area='Home' data-context='Position' data-toggle='ajax-modal' data-target='#edit-custom-view' data-action='EditCustomView' data-url='/Home/EditViewModal/'>Button</button>
And finally, the code that opens the modal and fetches the partial view.
public IActionResult EditViewModal(int id)
{
string partial = "_EditCustomView";
UserView userView = _userViewService.GetUserView(id);
return PartialView(partial, userView);
}
So, when I click on submit, the ajax function is triggered to submit the data, and the modal closes. If I edit the same item again without refreshing the page, the form gets submitted twice and so on, adding an additional post-event each time. My question is, why? I can't see any reason as to why it would do this. Any help is appreciated.
I cannot reproduce your problem since the code you provided is not complete. Maybe you can show us the placeholderElement and the scripts of editViewModal(this, event) function in the button click event.
Besides, in your case, we can call and display the a modal in the following way.
Here is a work demo:
Model:
public class UserView
{
public int Id { get; set; }
public string ViewName { get; set; }
public string Address { get; set; }
public string Tel { get; set; }
}
Partial View:
#model UserView
<div class="modal fade" id="edit-custom-view" tabindex="-1" role="dialog" aria-labelledby="edit-custom-view" aria-modal="true">
<div class="modal-dialog modal-dialog-scrollable modal-lg modal-notify modal-primary" role="document">
<div class="modal-content">
<form id="ModalFormEditCustomView" data-action="/Home/EditCustomView" enctype="multipart/form-data">
<div class="modal-body">
<div class="row">
<input type="text" asp-for="Id" hidden readonly />
<div class="col">
<div class="md-form form-group">
<label asp-for="ViewName">View Name</label>
<input type="text" required class="form-control" asp-for="ViewName" />
</div>
<div class="md-form form-group">
<label asp-for="Address">Address</label>
<input type="text" required class="form-control" asp-for="Address" />
</div>
<div class="md-form form-group">
<label asp-for="Tel">Tel</label>
<input type="text" required class="form-control" asp-for="Tel" />
</div>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="button" data-save="edit-view" class="btn btn-info waves-effect waves-light">Update</button>
<button type="button" class="btn btn-secondary waves-effect waves-light" data-dismiss="modal">Close</button>
</div><!--/modal-footer-->
</form>
</div>
</div>
</div>
Edit View:
#model UserView
<div class="row">
<div class="col-md-4">
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="ViewName" class="control-label"></label> :
<input asp-for="ViewName" class="form-control" readonly />
</div>
<div class="form-group">
<label asp-for="Address" class="control-label"></label> :
<input asp-for="Address" class="form-control" readonly />
</div>
<div class="form-group">
<label asp-for="Tel" class="control-label"></label> :
<input asp-for="Tel" class="form-control" readonly />
</div>
<div class="form-group">
<button name="btn" value="#Model.Id" class="btn btn-primary">Edit</button>
</div>
</div>
</div>
<div id="placeholderElement">
</div>
#section Scripts
{
<script>
$(".btn.btn-primary").on("click", function () {
var id = $(this).val();
$.ajax({
type: "get",
url: "/Home/EditViewModal?id=" + id,
success: function (result) {
$("#placeholderElement").html(result);
$("#edit-custom-view").modal('show');
}
});
})
$("#placeholderElement").on('click', '[data-save="edit-view"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.data('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$("#placeholderElement").find('.modal').modal('hide');
$("#ViewName").val(data.viewName);
$("#Address").val(data.address);
$("#Tel").val(data.tel);
});
});
</script>
}
Controller:
public IActionResult Edit()
{
var model = _db.UserViews.Find(1);
return View(model);
}
public IActionResult EditViewModal(int id)
{
string partial = "_EditCustomView";
var userView = _db.UserViews.Find(id);
return PartialView(partial, userView);
}
[HttpPost]
public JsonResult EditCustomView(UserView model)
{
var model1 = _db.UserViews.Find(model.Id);
model1.ViewName = model.ViewName;
model1.Address = model.Address;
model1.Tel = model.Tel;
_db.Update(model1);
_db.SaveChanges();
return Json(model1);
}
Where is this script located? If it is inside of the partial that is what is causing the issue for you. Every time the partial is pulled in an extra event is attached to the element.
This would cause the behavior that you are describing.

Passing the selected object id to the #HTML.Action parameter

Once again, I added an post, this time corrected, because the previous one was difficult to understand
I have a page where directories are shown something like a network drive
Here is the main Action to render view with catalogs:
public ActionResult Index(int? id)
{
return View(_context.NodeEntities.Where(x=>x.ParentId == id));
}
This action renders the view:
#model IEnumerable<Tree.Models.Node>
#{
ViewBag.Title = "Home Page";
}
<div class="container">
<div class="row">
#foreach (var node in Model)
{
<div class="col-md-3 one-node mx-3" id="#node.Id" onClick="Select(this.id)">
<img src="https://img.icons8.com/color/144/000000/folder-invoices.png">
#Html.ActionLink(node.Name, "Index", "Home", new { node.Id }, new { #style = "display:block;" })
</div>
}
</div>
<!-- Button trigger modal -->
<button id="change_name" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
Change name
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Change name:</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div id="modalBodyId" class="modal-body">
#Html.Action("EditName", "Home", new { id = 1 })
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
<script>
var div;
function Select(clicked_id) {
if (div != null) {
div.style.removeProperty('background-color');
}
div = document.getElementById(clicked_id);
div.style.backgroundColor = "lightgreen";
}
</script>
I would like to do something such that when a user clicks on a given folder, he is shown the option rename. After clicking change name, a pop-up appears in which the user can change the name of the selected folder. And what I wrote about it is done, but not completely. For me, it works so that when you click just change the name, a pop-up window appears and #HtmlAction is launched in the "modal-body":
public PartialViewResult EditName(int id)
{
Node node = _context.NodeEntities.FirstOrDefault(x => x.Id == id);
return PartialView("_EditName", node);
}
Here is the PartialView:
#model Tree.Models.Node
#using (Html.BeginForm("ZmienNazwe", "Home"))
{
<div class="form-group">
#Html.TextBoxFor(m => m.Name)
</div>
}
It works, but I passed in #Html.Action parameter "id = 3" and I would like to put there the id of the selected folder
Screen showing the problem
You cannot use Html.Action for this. It will execute ounce when the page loads, but you cannot update the route values dynamically client-side and have Html.Action execute again to fetch the new partial view. You would have to reload the whole page, and pass Html.Action the new value.
To do what you want you first have to add a custom click event to your "Change name" button that fetches the correct partial view, then displays the modal.
First remove data-toggle="modal" data-target="#exampleModalCenter" from you button so that Bootstrap doesn't wire up a click event to the button since we are creating our own.
<button id="change_name" type="button" class="btn btn-primary">
Change name
</button>
Next write some javascript to wire up your own click event to this button:
$('#change_name').on('click', function (e) {
e.preventDefault();
var id = 1; // TODO: Get id of selected node
$.get('/path/to/EditName/' + id, function (html) {
$('#exampleModalCenter .modal-body').html(html);
$('#exampleModalCenter').modal('show');
});
});
UPDATE
Most times I like to have my url generation on the server-side instead of having a string somewhere in javascript file or view.
To do this I will geneate my url with #Url.Action on the button.
On a button you can do this:
<button id="change_name" type="button" class="btn btn-primary" data-base-url="#Url.Action("EditName", "Controller")">
Change name
</button>
And javascript update:
var url = $(this).data('base-url');
$.get(url + '/' + id, function (html) {
Or simply use an <a> tag (instead of a button) and href attribute:
<a id="change_name" href="#Url.Action("EditName", "Controller")" class="btn btn-primary">
Change name
</a>
And javascript updates:
$.get(this.href+ '/' + id, function (html) {

Open modal dialogue in catch block

I have this code in my action
var singedUser = HttpContext.User.Identity.Name;
try
{
_purchaseService.PurchaseCard(singedUser, cardName);
}
catch
{
}
And I want this to open ONLY if the code enters the catch block
<div id="Modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Purchasing Card</h4>
</div>
<div class="modal-body">
<p>You have unsufficient funds!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
And here is my button
<a class="button btn btn-success"
asp-controller="Store" asp-action="Buy"
asp-route-data ="#card.Name">Buy (#card.Price coins)</a>
I would appreciate if someone would tell me how I can open this dialogue box in the same page only if the code enters the catch block
You can also use an ajax call to return the partial view and add it to the DOM. Setting up a modal to load a partial view is actually pretty straight forward :
Create partial view : _ModalContent.cshtml
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Purchasing Card</h4>
</div>
<div class="modal-body">
<p>You have unsufficient funds!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
Modify your Index page :
<a id="button1" class="button btn btn-success"
asp-controller="Store" asp-action="Buy"
asp-route-data ="#card.Name">Buy (#card.Price coins)</a>
<div id="myModal"></div>
#section Scripts{
<script type="text/javascript">
$(function () {
$.ajaxSetup({ cache: false });
$("#button1").on("click", function (e) {
$('#myModal').load(this.href, function () {
$('#Modal').modal({
keyboard: true
}, 'show');
});
return false;
});
});
</script>
}
Controller function :
public IActionResult buy(string data)
{
.....
{
return PartialView("_ModalContent");
}
}
I would pass a variable through the ViewBag on the controller/action. Something like this in the controller:
var singedUser = HttpContext.User.Identity.Name;
try
{
_purchaseService.PurchaseCard(singedUser, cardName);
}
catch
{
ViewBag.ShowModal = false;
}
Then toggle whether or not to trigger JQuery to show the Modal in the scripts section of the view:
#section Scripts{
<script>
#if(ViewBag.ShowModal == true){
#Html.Raw("$('#Modal').modal('show');");
}
</script>
}

Child actions are not allowed to perform redirect actions

I used modal in my edit page and here is my code:
In the View
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Edit
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Edit Event Information</h4>
</div>
<div class="modal-body">
#Html.Action("Edit", "Admin",new { id = Model.events_info_id,#class = "btn btn-warning"})
</div>
</div>
</div>
</div>
This the controller to get the information to be display in the modal:
[ChildActionOnly]
public ActionResult Edit(int id = 0)
{
Events_Info_tbl events_info_tbl = db.Events_Info_tbl.Find(id);
if (events_info_tbl == null)
{
return HttpNotFound();
}
return PartialView(events_info_tbl);
}
This the View of the content of the Modal:
#model Online_Ballot.Models.Events_Info_tbl
<script src="~/Scripts/Datepicker.js"></script>
<div class="modal-body" style="color:green">
<h2>Edit Events</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.events_info_id)
<div class="form-group">
<label for="usr">Event Name:</label>
#Html.EditorFor(model => model.events_name, new { #class="form-control"})
#Html.ValidationMessageFor(model => model.events_name)
</div>
<div class="form-group">
<label for="usr">Votation Date:</label>
#Html.EditorFor(model => model.events_votation_date, new { #id="voters_bdate"})
#Html.ValidationMessageFor(model => model.events_votation_date)
</div>
<div class="form-group">
<label for="usr">Votation Place:</label>
#Html.EditorFor(model => model.events_place, new { #class="form-control"})
#Html.ValidationMessageFor(model => model.events_place)
</div>
<div class="form-group">
<label for="comment">Event Description:</label>
#Html.TextAreaFor(model => model.events_desc)
</div>
<div class="form-group">
<label for="usr">Is active:</label>
#Html.EditorFor(model => model.is_active, new { #class="form-control"})
#Html.ValidationMessageFor(model => model.is_active)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
}
This Controller will update the data:
// POST: /Admin/Edit/5
[ValidateAntiForgeryToken]
public ActionResult Edit(Events_Info_tbl events_info_tbl)
{
if (ModelState.IsValid)
{
db.Entry(events_info_tbl).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(events_info_tbl);
}
When I try to run this code I got this error:
Child actions are not allowed to perform redirect actions.
But, it updates the data, I guess it not allowed to call RedirectToAction function but I need to. How I am going to fix this one?
Your child action shouldn't be attempting to update anything. It should be getting data, populating something, and returning some view.
You probably want to split your action into two actions. One for rendering the "Edit" form and another for updating that form.
[HttpPost]
public ActionResult Edit(Events_Info_tbl events_info_tbl)
{
if (ModelState.IsValid)
{
//Save
return RedirectToAction("Index");
}
//Return view
//NOTE: Make sure your page state is preserved i.e. your modal is open
return View(events_info_tbl);
}
[ChildActionOnly]
public PartialViewResult RenderEditForm(int id)
{
//Build form data
return PartialView("_EditForm");
}
Another note, you have some collision here to how the "Editor" and "Partial" razor helpers can work. Child actions are good for views where it doesn't make sense to fit the data into the controllers model. If the model fits then just use "Editor" or "Partial"
UPDATE
This...
#Html.Action("Edit", "Admin",new { id = Model.events_info_id,#class = "btn btn-warning"})
appears to be pointing to this...
public ActionResult Edit(Events_Info_tbl events_info_tbl)
when you actually want it to point to this...
public ActionResult Edit(int id = 0)
edit the controller accordingly in Html.Action
#Html.Action("Edit", "MyController",new { id = Model.events_info_id,#class = "btn btn-warning"})

HTML.Partial() is not working when displaying it?

In Asp.net mvc 5. we have a login page which implements HTML.BeginForm() to post data to controller , if the username and password are incorrect, we are sending error back to the front end using partial views. Everything work fine, In case of error only error message is displayed on the screen and nothing else.
Controller
[HttpPost]
public ActionResult SingleSSOMPLogin(SSoStateModel model)
{
//Check the Code with SP providers and Authorization server.
if(model.SAMLAssertion.validMPData)
{
return RedirectToAction("SSOServiceMP" , "SAML");
}else
{
//Error message processed.
model.errorMessage = SSOState.SAMLAssertion.errorMessage;
return PartialView("_LoginError" , model);
}
}
The view contain the following Code
<div class="peripheral">
<div class="panel panel-default panel-peripheral">
#{Html.Partial("_LoginError", Model);}
<div class="panel-heading clearfix">Please Log In</div>
<div class="panel-body">
<div class="brand-logo eop-logo">
<script type="text/javascript">
function changeImage() {
document.getElementById("Logo").src = '#Url.Content("~/Content/images/TopLogo.gif")';
}
</script>
<img id="Logo" width="200" src='#Url.Content("~/Content/images/TopLogo.gif")' onerror="changeImage()" />
#{ Html.EnableClientValidation(true);}
<!--Ajax call to Controller-->
#using (Html.BeginForm("SingleSSOMPLogin", "Accounts"))
{
#Html.ValidationSummary(true);
<div id="group-email" class="form-group col-md-12 ">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", placeholder = "Please enter your Email address" })
#Html.ValidationMessageFor(m => m.Email)
</div>
<div id="group-password" class="form-group col-md-12">
#Html.PasswordFor(m => m.Password, new { #class = "form-control", placeholder = "Please enter your password" })
#Html.ValidationMessageFor(m => m.Password)
</div>
<div class="form-group">
<div class="col-md-12">
<button type="submit" class="btn btn-primary pull-left">Login</button>
<a id="forgot" href='#Url.Action("ForgotPassword","Accounts")' class="btn btn-link btn-sm pull-right">Forgot your password?</a>
</div>
</div>
}
</div>
</div>
</div>
</div>
Partial View
#{
Layout = null;
}
#if (Model.Result!= null)
{
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<strong>#Model.Result.errorMessage</strong>
</div>
}
When Error occur, I get redirect to same view again with all query parameter gone and display only error message.
How to solve following issue?
The partial view will return only the fragment you defined.
So when called from a "complete" view with
#{Html.Partial("_LoginError", Model);}
it will generate the corresponding part of the view.
In your situation what is most common is to add a model error and return the complete view (that must have a ValidationSummary section):
[HttpPost]
public ActionResult SingleSSOMPLogin(SSoStateModel model)
{
//Check the Code with SP providers and Authorization server.
if(model.SAMLAssertion.validMPData)
{
return RedirectToAction("SSOServiceMP" , "SAML");
}else
{
//Error message processed.
ModelState.AddModelError("error", SSOState.SAMLAssertion.errorMessage);
return View(model);
}
}
If you want to use the partial view you have to call it from an javacript ajax call and insert the response in your page. With jQuery it is something more or less like:
$.ajax({ url: <partial view url>,
type: 'GET',
success: function (result) {
$(updateSelector).hide().html(result).effect("fade", "fast");
}
});

Categories

Resources