MVC reusable search window [closed] - model-view-controller

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
In mvc how to create customer search page. Also how to call invoke this as modal popup from other views button (need to call in different views). How to pass the customerid and customername after searching to the page invoking the search page. Requirement is reusable customer search window.
Tried with bootstrap modal popup

Create a partial view _PartialSearch.cshtml and include it in your _Layout.cshtml file:
#Html.Partial("_PartialSearch")
The partial view will call the Search method in your controller and get the search results.
Views/Shared/_PartialSearch.cshtml
<!-- Modal -->
<div id="myModal" class="modal fade" 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">Search window</h4>
</div>
<div class="modal-body">
<div>
<input type="search" id="searchString"><button type="submit" id="search">Search</button>
</div>
<br/>
<div id="result"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
#{
<script>
$(function () {
//Init the result
$("#result").load("#Url.Action("GetAll", "Home")");
$("#search").click(function() {
var searchString = $("#searchString").val();
$.ajax({
type: "POST",
url: "#Url.Action("Search", "Home")",
data: '{searchString: "' + searchString + '" }',
contentType: "application/json; charset=utf-8",
dataType: "html",
success: function(response) {
$('#result').html(response);
},
failure: function(response) {
alert(response.responseText);
},
error: function(response) {
alert(response.responseText);
}
});
});
});
</script>
}
Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("Another Page", "AnotherPage", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
#Html.Partial("_PartialSearch")
</body>
</html>
Create a Customer model to store your customer's data
Models/Customer.cs
namespace SearchModal.Models
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Create a Movie model to store your search data
Models/Movie.cs
namespace SearchModal.Models
{
public class Movie
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
Create a SearchResultVm viewmodel to store your view data
Viewmodels/SearchResultVm.cs
using System.Collections.Generic;
using SearchModal.Models;
namespace SearchModal.ViewModels
{
public class SearchResultVm
{
public List<Movie> Movies { get; set; }
}
}
Create a SessionDataManager manager to manage your Customer session
Managers/SessionDataManager.cs
using System.Web;
using System.Web.SessionState;
using SearchModal.Models;
namespace SearchModal.Managers
{
public class SessionDataManager : ISessionDataManager
{
private HttpSessionState CurrentSession => HttpContext.Current?.Session;
private object GetSessionObject(string key, bool redirectToSessionEnd = true)
{
var obj = CurrentSession?[key];
if (obj == null)
{
//no session
}
return obj;
}
private void SetSessionObject<T>(string sessionObjectName, T value)
{
CurrentSession[sessionObjectName] = value;
}
public Customer Customer
{
get => GetSessionObject("Customer") as Customer;
set => SetSessionObject("Customer", value);
}
}
public interface ISessionDataManager
{
Customer Customer { get; set; }
}
}
Create a HomeController controller to handle your different views that has the search button (i.e. Index and AnotherPage)
Create a Search method to handle your search request and return a partial view with the results
Controllers/HomeController.cs
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using SearchModal.Managers;
using SearchModal.Models;
using SearchModal.ViewModels;
namespace SearchModal.Controllers
{
public class HomeController : Controller
{
private ISessionDataManager _sessionDataManager;
private List<Movie> _movies;
public HomeController()
{
//TODO Inject through Dependency Injection
_sessionDataManager = new SessionDataManager();
_movies = new List<Movie>
{
new Movie
{
Id = 1, Name="Die Hard", Description = "Christmas movie"
},
new Movie
{
Id = 2, Name="Armageddon", Description = "End of the world"
},
new Movie
{
Id = 3, Name="Love actually", Description = "Chick flick"
}
};
}
public ActionResult Index()
{
//Set customer details
var customer = new Customer {Id = 1, Name = "Bob"};
_sessionDataManager.Customer = customer;
return View();
}
public ActionResult AnotherPage()
{
//Get customer info
var customer = _sessionDataManager.Customer as Customer;
//Do something with customer info
return View();
}
public ActionResult GetAll()
{
//Get customer info
var customer = _sessionDataManager.Customer as Customer;
//Do something with customer info
var viewModel = new SearchResultVm
{
Movies = _movies
};
return PartialView("_SearchResult", viewModel);
}
public ActionResult Search(string searchString)
{
//Get customer info
var customer = _sessionDataManager.Customer as Customer;
//Do something with customer info
var viewModel = new SearchResultVm
{
Movies = _movies.Where(m => m.Name.Contains(searchString)).ToList()
};
return PartialView("_SearchResult", viewModel);
}
}
}
Create an Index view to show your search button. The only line you need to include in other views are this:
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
Views/Home/Index.cshtml
<div>
<h1>Index</h1>
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
</div>
Create an AnotherPage view for another page with the search button
Views/Home/AnotherPage.cshtml
<div>
<h1>Another Page</h1>
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
</div>
Create a _SearchResult partial view to show results
Views/Home/_SearchResult.cshtml
#model SearchModal.ViewModels.SearchResultVm
<br/>
<b>Results: </b><br/>
#foreach (var movie in Model.Movies)
{
<b>#movie.Name</b> #:- #movie.Description<br />
}
Output:

Related

Model binding is not properly working in input parameter controller in .Net Core

I am trying to Alldata transfer a from Model to ViewModel.But the input parameter can't input several data. for that this data I can not use my session to create a cart system. Here is my code.`enter code here.
public class ProductVm: Spray
{ }
public class Spray
{
public int Id { get; set; }
[Required]
public String Name { get; set; }
[Required]
public decimal Price { get; set; }
public String Image { get; set; }
public String Image1 { get; set; }
[Required]
public String ProductColor { get; set; }
public DateTime Date { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public int Size { get; set; }
[Required]
public String Description { get; set; }
[Display(Name = "Product Type")]
public int ProductTypeId { get; set; }
[ForeignKey("ProductTypeId")]
public ProductTypes ProductTypes { get; set; }
}
[HttpGet]
public ActionResult Details(int? id)
{
if (id == null)
{
return NotFound();
}
var hi = _db.Spray.Include(c => c.ProductTypes).FirstOrDefault(c => c.Id == id);
ProductVm product = new ProductVm
{
Name = hi.Name,
Id = hi.Id,
Image = hi.Image,
Quantity = hi.Quantity,
Price = hi.Price,
};
if (product == null)
{
return NotFound();
}
return View(product);
}
[HttpPost]
[ActionName("Details")]
public async Task <IActionResult> ProductDetails(ProductVm pb)
{
List<Spray> sprays = new List<Spray>();
//if (id == null)
//{
// return NotFound();
//}
//var yes = _db.Spray.Include(c => c.ProductTypes).FirstOrDefault(c => c.Id == id);
ProductVm product = new ProductVm()
{
Name = pb.Name,
Id=pb.Id,
Image=pb.Image,
Quantity=pb.Quantity,
Price=pb.Price,
};
if (product == null)
{
return NotFound();
}
sprays = HttpContext.Session.Get<List<Spray>>("sprays");
if (sprays == null)
{
sprays = new List<Spray>();
}
sprays.Add(product);
HttpContext.Session.Set("sprays", sprays);
return RedirectToAction(nameof(Index));
}
#model ProductVm
#{
ViewData["Title"] = "Details.Cshtml";
}
#*#using OnlineShop.Utility
#using Microsoft.AspNetCore.Http
#inject IHttpContextAccessor HttpContextAccessor
#{
List<Laptop> laptops = HttpContextAccessor.HttpContext.Session.Get<List<Laptop>>("laptops");
Laptop laptop = null;
if (laptops != null)
{
laptop = laptops.FirstOrDefault(c => c.Id == Model.Id);
}
}
<br />*#
<h2 class="text-info"> Product Details</h2>
</br></br>
#*<form method="post" asp-action="" enctype="multipart/form-data">*#
<form method="post" asp-action="" enctype="multipart/form-data">
<div class="row">
<div class="col-1">
<img src="~/#Model.Image" style="width:100%" onclick="myFunction(this);">
</br></br>
<img src="~/#Model.Image1" style="width:100%" onclick="myFunction(this);">
</div>
<div class="col-4 container">
<span onclick="this.parentElement.style.display='none'" class="closebtn">×</span>
<img id="expandedImg" style="width:100%">
<div id="imgtext"></div>
</div>
<div class="col-4">
<h2>#Model.Name</h2>
<p><b>#Model.Description</b></p>
<h4>#Model.Price $</h4>
<small class="text-danger">Clearence</small>
</br>
<hr>
<h4>Size:#Model.Size</h4>
<h6>Product Color:#Model.ProductColor</h6>
</br></br></br></br>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<div class="col-sm-12 col-xs-12 spinner-block">
<div class="number-spinner">
<div class="input-group number-spinner">
<b class="mr-4"> <label asp-for="#Model.Quantity"></label></b></br>
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number btncartsniper" data-type="minus" data-dir="dwn"><span class="fa fa-minus fa-sm"></span></button>
</span>
<input asp-for="#Model.Quantity" class="form-control input-number Snippper_qty" value="0" type="number">
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number btncartsniper" data-type="plus" data-dir="up"><span class="fa fa-plus fa-sm"></span></button>
</span>
</div>
</div>
</div>
#*#if (Model.Quantity > 0)
{
<h1>This Product Is InStock</h1>
}
else
{
<h1>Not InStock</h1>
}*#
</br>
<input type="submit" class="btn btn-dark form-control" value="Add To Cart" />
</div>
</div>
below picture, I am successful to transfer data to ViewModel but next failed to data-bind.
enter image description here
enter image description here
I am a beginner. Please, anyone, help me
can't scope this image under input tag
As #Ben mentioned, you can use hidden input to store the value that img needs to pass like:
<img src="~/#Model.Image" style="width:100%" onclick="myFunction(this);">
<input type="hidden" asp-for="Image">
Another way is to use ajax to pass any model you want:
<img src="~/#Model.Image" style="width:100%" onclick="myFunction(this);" data="#Model.Image">
<script>
var productVm =
{
//other fields
"Image": $("#Image").attr("data"),
}
$.ajax({
url: '/Home/Details',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(productVm)
});
</script>
Your Quantity property is passing back through pb because it has an <input> property.
You need to make sure anything you want to pass back to POST action has an input tag associated with it. If you don't want the user to see it, type="hidden" is a good candidate. However, if those fields are not editable by a user you could simply just grab them in the POST action too if you need them.

how to load data in table and bind the same to view Model class in .net core mvc (without refreshing the page)

I'm trying to add data in table via server but unable to succeed. I tried many things but nothing worked. I'm getting the data from the server but unable to populate that in table.. can someone please help me out?
I'm getting this :
"DataTables warning: table id=particlarsTable - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1"
Let me explain my code first:
(In View)
When I click on "Add New Particular" button, bootstrap modal will popup with input fields, those fields will send to the server then again back to view and populate the table with the same data without refreshing the whole page.
I'm stuck on the last stage, I'm getting the data on UI/View in ajax success handler but unable to load that data in table.
here is my view :
<form class="form-horizontal" method="post" id="createAdHocForm">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Select Flat</label>
<select asp-for="AdHocInvoice.FlatRid" asp-items="#(new SelectList(Model.Flats,"FlatRid","FlatNumber"))" class="form-control form-control-sm selectpicker" data-live-search="true">
<option selected disabled value="">Select One</option>
</select>
</div>
</div>
</div>
<table class="table table-sm table-responsive-md nowrap w-100" id="particlarsTable">
<thead class="thead-light">
<tr>
<th>Particulars</th>
<th>Amount</th>
<th></th>
</tr>
</thead>
<tbody class="bg-white">
#foreach (var item in Model.AdHocInvoice.FlatInvoiceItems)
{
<tr>
<td>#item.Particular</td>
<td>#item.Amount</td>
<td></td>
</tr>
}
</tbody>
</table>
<button class="btn btn-sm btn-outline-info" type="button" onclick="showParticularForm()">Add New Particular</button>
<hr />
<div class="row text-center">
<button class="btn btn-sm btn-outline-success mx-auto" type="submit">Submit</button>
</div>
</form>
bootstrap modal to fill the table :
<div class="modal fade" id="particularWindow">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Invoice Items</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<form class="form-horizontal" method="post" id="particularForm">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<label>Enter Particular</label>
<input id="particularName" name="particular" class="form-control form-control-sm" required />
</div>
</div>
<div class="col-md-5">
<label>Amount</label>
<input id="particularAmount" name="amount" class="form-control form-control-sm" required />
</div>
<div class="col-md-2">
<button class="btn btn-sm btn-outline-success mt-4" id="btnParticularSubmit" type="button" onclick="addParticular()">Add</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
Scripts:
<link rel="stylesheet" href="~/DataTables/datatables.min.css" />
<script type="text/javascript" src="~/DataTables/datatables.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#particlarsTable').DataTable();
});
function showParticularForm() {
$('#particularWindow').modal('show');
}
function addParticular() {
var particular = $('#particularName').val();
var amount = $('#particularAmount').val();
$.ajax({
url: '/FlatInvoice/AddParticular',
data: 'particular=' + particular + '&amount=' + amount,
success: function (response) {
$('#particlarsTable').DataTable().ajax.reload()
}
});
}
</script>
Action Method on controller:
public JsonResult AddParticular(string particular, decimal amount)
{
_flatInvoiceViewModel.AdHocInvoice.FlatInvoiceItems.Add(new FlatInvoiceItem { Particular = particular, Amount = amount });
return Json(_flatInvoiceViewModel);
}
Class/Model:
public class FlatInvoiceItem
{
public Guid FlatInvoiceItemRid { get; set; }
public Guid FlatInvoiceRid { get; set; }
public Guid FundRuleRid { get; set; }
public string Particular { get; set; }
public decimal Amount { get; set; }
}
NOTE: this code is in initial phase, I need that input data on server for further process(will add code later) so don't want to use $.('#table_body_id').append("<tr>..</tr>"); type of code.
1.Firstly,reload() is used to send request back to the method which display the DataTable initially(e.g. name this method Test).
2.Secondly,From your AddParticular method,you just add a data to the list but the lifetime is just one request,so when you reload to Test method,the list still contains the initial data without new data.
Conclusion: I suggest that you could save data to database.And get data from database.
Here is a working demo about how to use DataTabale:
1.Model:
public class Test
{
public int Id { get; set; }
public AdHocInvoice AdHocInvoice { get; set; }
}
public class AdHocInvoice
{
public int Id { get; set; }
public string Name { get; set; }
public List<FlatInvoiceItem> FlatInvoiceItems { get; set; }
}
public class FlatInvoiceItem
{
public int Id { get; set; }
public Guid FlatInvoiceItemRid { get; set; }
public Guid FlatInvoiceRid { get; set; }
public Guid FundRuleRid { get; set; }
public string Particular { get; set; }
public decimal Amount { get; set; }
}
public class ViewModel
{
public string Particular { get; set; }
public decimal Amount { get; set; }
}
2.View:
<form class="form-horizontal" method="post" id="createAdHocForm">
<table class="table table-sm table-responsive-md nowrap w-100" id="particlarsTable">
<thead class="thead-light">
<tr>
<th>Particulars</th>
<th>Amount</th>
<th></th>
</tr>
</thead>
#*<tbody class="bg-white">
#foreach (var item in Model.AdHocInvoice.FlatInvoiceItems)
{
<tr>
<td id="particular">#item.Particular</td>
<td id="amount">#item.Amount</td>
<td></td>
</tr>
}
</tbody>*# //DataTable no need to add this tbody
</table>
<button class="btn btn-sm btn-outline-info" type="button" onclick="showParticularForm()">Add New Particular</button>
<hr />
<div class="row text-center">
<button class="btn btn-sm btn-outline-success mx-auto" type="submit">Submit</button>
</div>
</form>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function () {
//$('#particlarsTable').DataTable();
$('#particlarsTable').DataTable({
ajax: {
type: 'GET',
dataType: 'JSON',
url: '#Url.Action("Test", "Home")',
},
columns: [
{ 'data': 'particular' },
{ 'data': 'amount' }
]
})
});
function showParticularForm() {
$('#particularWindow').modal('show');
}
function addParticular() {
var particular = $('#particularName').val();
var amount = $('#particularAmount').val();
$.ajax({
url: '/Home/AddParticular',
data: 'particular=' + particular + '&amount=' + amount
}).done(function (data) {
$('#particularWindow').modal('hide');
$('#particlarsTable').DataTable().ajax.reload();
});
}
</script>
3.Controller:
public class HomeController : Controller
{
private readonly MyDbContext _context;
public HomeController(MyDbContext context)
{
_context = context;
}
public IActionResult Index()
{
return View();
}
public JsonResult Test()
{
var _flatInvoiceViewModel = _context.Test.Include(i=>i.AdHocInvoice)
.ThenInclude(a=>a.FlatInvoiceItems).Where(i => i.Id == 1).FirstOrDefault();
var list = new List<ViewModel>();
foreach (var item in _flatInvoiceViewModel.AdHocInvoice.FlatInvoiceItems)
{
var model = new ViewModel() { Amount = item.Amount, Particular = item.Particular };
list.Add(model);
}
return Json(new { data = list });
}
public void AddParticular(string particular, decimal amount)
{
var _flatInvoiceViewModel = _context.Test.Include(i => i.AdHocInvoice)
.ThenInclude(a => a.FlatInvoiceItems).Where(i => i.Id == 1).FirstOrDefault();
_flatInvoiceViewModel.AdHocInvoice.FlatInvoiceItems.Add(new FlatInvoiceItem { Particular = particular, Amount = amount });
_context.SaveChanges();
}
4.Result:
Reference:
https://datatables.net/examples/data_sources/ajax.html
https://stackoverflow.com/a/59449895/11398810

How do you connect a POST to a different razor page loaded via AJAX into a modal popup?

Edit: Have marked up where the error in the original code was stopping this from working.
I can find plenty of info and examples of this on MVC, but doesn't seem to apply for Razor Pages?
Simple scenario: I have a page (FooList) showing a list of Foo items. Each has an Edit button. This opens a modal popup with the layout (and data) coming from a second page (FooEdit).
The Edit form appears and populates fine, but I can't work out how to get it to post the data back to the FooEdit code behind?
List page, FooList.cshtml
#page
#model Pages.FooListModel
<table>
#foreach (var item in Model.FooListVM)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a onclick="openModal(#item.ID);">Edit</a>
</td>
</tr>
}
</table>
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header border-bottom-0">
<h5 class="modal-title" id="exampleModalLabel">Edit Foo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form> <---- Edit: ** This shouldn't be here **
<div class="modal-body">
</div>
</form> <---- Edit
</div>
</div>
</div>
<script>
function openModal(i) {
$.get("FooEdit?id="+i,
null,
data => {
$("#editModal").modal("show");
$("#editModal .modal-body").html(data);
});
};
</script>
Code behind, FooList.cshtml.cs
public class FooListModel : PageModel
{
public IList<FooListVM> FooListVM { get; set; }
public void OnGet()
{
FooListVM = new List<FooListVM>
{
new FooListVM { ID = 1, Name = "Foo 1" },
new FooListVM { ID = 2, Name = "Foo2" }
};
}
}
public class FooListVM
{
public int ID { get; set; }
public string Name { get; set; }
}
Second page for the popup, FooEdit.cshtml
#page
#model Pages.FooEditModel
#(Layout=null)
<form method="post">
<input asp-for="FooEditVM.Name" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff1" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff2" class="form-control" /><br />
<input type="submit" value="Save"/>
</form>
And the code behind for the popup, FooEdit.cshtml.cs
public class FooEditModel : PageModel
{
[BindProperty]
public FooEditVM FooEditVM { get; set; }
public void OnGet(int id)
{
FooEditVM = new FooEditVM
{
Name = $"This is item {id}",
Stuff1 = "Stuff1",
Stuff2 = "Stuff2"
};
}
public void OnPost(int id)
{
// How do we get to here???
var a = FooEditVM.Name;
}
}
public class FooEditVM
{
public string Name { get; set; }
public string Stuff1 { get; set; }
public string Stuff2 { get; set; }
}
I've been through all the MS Tutorial stuff on Asp.net Core 2.2, but it doesn't seem to cover this.
Also as a side question, although it works, is there a "ASP helper tag" way of doing the ajax bit?
Have realised the problem was the 'form' tag in the Modal Dialog markup that was clashing the 'form' tag from the partial page. Removing it fixed everything using:
In FooEdit.cshtml
<form id="editForm" asp-page="FooEdit">
. . .
</form>
In FooEdit.cshtml.cs
public void OnPost()
{
// Fires in here
}
I'm pretty sure the fooedit page is going to need some jQuery to handle this.
See below for what I would do in the fooedit page.
#page
#model Pages.FooEditModel
#(Layout=null)
<form id=fooedit method="post" action="FooEdit">
<input asp-for="FooEditVM.Name" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff1" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff2" class="form-control" /><br />
<input type="submit" value="Save"/>
</form>
<SCRIPT language="JavaScript" type="text/Javascript">
<!--
$(document).ready(function(e) {
$("#fooedit").submit(function(e) {
e.preventDefault();
var form_data = $(this).serialize();
var form_url = $(this).attr("action");
var form_method = $(this).attr("method").toUpperCase();
$.ajax({
url: form_url,
type: form_method,
data: form_data,
cache: false,
success: function(returnhtml){
$("#editModal.modal-body").html(returnhtml);
}
});
});
});
</SCRIPT>

Validation error message not displayed in Asp.Net Core 2 MVC partial view

I have an index page with a list of "workbooks" titles and for each workbook, there is a "share" button. When pressing the button a bootstrap model (i.e. dialog) appears which displays the title of the workbook and a textarea allowing the user to type in a sharees email addresses.
When the user presses on the "share" button, I am calling a javascript function which calls a controller action that returns a partial view containing the modal dialog with a form inside it. The problem is that after pressing the submit button (i.e. "Share") there are no validation errors being shown to the user and I am not sure why that is. Could anyone provide some ideas, please?
That is my main (index.cshtml) page:
#model DNAAnalysisCore.Models.WorkBookModel
#{
}
#section BodyFill
{
<script type="text/javascript">
function showSharingView(title) {
var url = "#Url.Action("ShowShareDialog", "Home")" + "?workbookTitle=" + encodeURI(title);
$('#shareFormContainer').load(url,
function() {
$('#shareFormModal').modal("show");
});
}
function hideSharingView() {
$('#shareFormModal').modal("hide");
}
</script>
<div id="shareFormContainer" >
<!--PLACEHOLDER FOR SHARE DIALOG -->
</div>
<div class="workbook-container">
<table class="table">
<tbody>
#foreach (var workbook in Model.Workbooks)
{
<tr>
<td>#Html.ActionLink(workbook.Name, "Open", "OpenAnalytics", new {id = Model.Id, workbook = workbook.Name})</td>
<td>
<button title="Share" class="share-button" onclick='showSharingView("#workbook.Name")'> </button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
That is my Controller:
public class HomeController : Controller
{
[HttpGet]
public IActionResult ShowShareDialog(string workbookTitle)
{
var shareModel = new ShareModel
{
Title = workbookTitle
};
return PartialView("_ShareView", shareModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ShareWorkbook(string emails, string title)
{
var share = new ShareModel
{
Emails = emails
};
// TODO EMAIL THE SHARED WORKBOOK using the 'title' of the workbook and the 'email' string value
// return no content to avoid page refresh
return NoContent();
}
}
This is my partial view/modal dialog (_ShareView):
#using DNAAnalysisCore.Resources
#model DNAAnalysisCore.Models.ShareModel
<!-- Modal -->
<div class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Share Workbook - #Model.Title</h4>
</div>
#using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post))
{
<div class="modal-body">
<label>#BaseLanguage.Share_workbook_Instruction_text</label>
<div class="form-group">
<textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="#BaseLanguage.ShareDialogPlaceholder"></textarea>
#* TODO add client-side validation using jquery.validate.unobtrusive.js. See US268276 *#
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<input asp-for="Title" />
</div>
<div class="modal-footer">
<button type="submit" onclick="hideSharingView()" class="btn btn-primary">Share</button>
<button id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
}
</div>
</div>
</div>
#section Scripts {
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
This is my ShareModel:
public class ShareModel
{
[HiddenInput]
public string Title { get; set; }
[Required]
public string Emails { get; set; }
}
The form is not added to the page when the page loads, the unobtrusive validation will not pick it up.A simple solution is to use $.validator.unobtrusive.parse("#id-of-the-form");.Refer to here.
1.Add id to your form in _ShareView partial view:
#using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post,new { #id="partialform"}))
2.Introduce validation file _ValidationScriptsPartial.cshtml into main page(Index.cshtml) and manually register the form with the unobtrusive validation.
#section Scripts
{
#await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript">
function showSharingView(title) {
var url = "#Url.Action("ShowShareDialog", "Home")" + "?workbookTitle=" + encodeURI(title);
$('#shareFormContainer').load(url,
function() {
$('#shareFormModal').modal("show");
$.validator.unobtrusive.parse("#partialform");
});
}
function hideSharingView() {
$('#shareFormModal').modal("hide");
}
</script>
}

Passing Model Data to a Bootstrap Modal on click

I'm extremely new to MVC and I don't know how to make this work-
I have a model that stores different news items based on categories:
NewsModel.cs:
public class NewsModel
{
public int ID { get; set; }
public string category { get; set; }
public String headline { get; set; }
public string source { get; set; }
public DateTime date { get; set; }
public string body { get; set; }
public string summary { get; set; }
}
I have a View that displays each of the news items as a list Item:
Sports.cshtml:
#model IEnumerable<Test.Models.NewsModel>
#foreach (var item in Model)
{
<div class="news_target-left floatleft">
<div class="image-container">
<img src="~/Content/Images/demo_img.png" alt="website template image">
<div class="top-left-text">
#item.category
</div>
</div>
<h3>#item.headline</h3>
<p> #item.summary </p>
<p class="single_cat_left_content_meta"><span>#item.source</span> | #item.date</p>
<span class="readmore">#Html.ActionLink("Read More", "NewsModal", "Home", #item)</span>
</div>
}
When the user clicks on Read More, I want to load a bootstrap modal that gets the current model object and displays the entire news data in detail. Currently, the readmore span uses an Html actionlink that does not seem to be working. I want to load the modal using Ajax but cannot figure out how to do so.
This is the bootstrap Modal that I have:
NewsModal.cshtml:
#model Test.Models.NewsModel
<div id="newsModal" 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">Leadsquared Express</h4>
</div>
<div class="modal-body">
<h2>#Model.headline</h2>
<i><small>#Model.source</small></i>
<p>#Model.body</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The Model is in Models/NewsModel
The Sports View is in Views/Categories/
The Sports controller Action is in Controllers/Categories:Sports
The NewsModal is currently in Views/Categories/. I have tried putting this view in Shared, as well as its own folder, but I'm obviously doing something wrong.
Any help?
Edit:
I used this link to make the following changes but clicking on "Read more" does not open the modal popup.
http://www.c-sharpcorner.com/UploadFile/092589/implementing-modal-pop-up-in-mvc-application/
changed <span class="readmore">#Html.ActionLink("Read More", "NewsModal", "Home", #item)</span> in Sports.cshtml to
<a id="openmodal "href="javascript:void(0)" class="readmore" data-model="#Json.Encode(#item)">Read More</a>
and added this script:
$(document).ready(function () {
var url = "/Home/NewsModal";
var model = $("#openmodal").attr("data-model");
alert("script running- sports.html");
$.ajax({
type: 'GET',
url: '/Home/NewsModal',
data: model,
contentType: 'application/json; charset=utf-8',
success: function (data, status, settings) {
$("#openmodal").html(data);
},
error: function (ajaxrequest, ajaxOptions, thrownError) {
$("#openmodal").html('Failed to load more content');
}
});
});
Additionally, this is the Action Method I have for the Modal Popup, in HomeController:
public ActionResult NewsModal(NewsModel tempData)
{
NewsModel currentItem = new NewsModel();
currentItem = tempData;
return PartialView("NewsModal", currentItem);
}
You can do by make a click event by using Anchor tag instead ActionLink,
and in that you can do like this.
Open a Modal by jQuery
function openModal()
{
$('#newsModal').modal('show');
}
// $('#newsModal').modal('toggle');
// $('#newsModal').modal('show');
// $('#newsModal').modal('hide');
OR can do directly with data-target,
<button type="button" data-toggle="modal" data-target="#newsModal">Launch modal</button>

Resources