I have a Search Partial View that I want to return but I want to return it by running it through an exisiting Partial View Result in the Controller instead of loading the view directly.
So, in the controller I have:
public ActionResult Index()
{
return View();
}
public PartialViewResult _GetSearch(List<Search> model)
{
return PartialView("_Search", model);
}
[ValidateAntiForgeryToken()]
public PartialViewResult _BeginSearch(string search)
{
var results = SearchModels(search).ToList();
return PartialView("_GetSearch", results);
}
And in the search view itself I have:
<div class="col-md-4">
<div id="modelSearch" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-search"></i> Search by Model / Manufacturer</h3>
</div>
<div class="panel-body">
#using (Ajax.BeginForm("_BeginSearch", "Home", new AjaxOptions() { UpdateTargetId = "modelSearch" }))
{
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBox("search", null, new {id = "name", #class = "form-control", placeholder = "Please enter a manufacturer or model"})
<span class="input-group-btn">
<button id="search" class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
if (Model != null)
{
<div class="searchResults fade">
#foreach (var s in Model)
{
<div class="result">
#switch (s.ResultType)
{
case "Man":
#s.Manufacturer
break;
case "Mod":
#s.Manufacturer #s.Model
<img src="~/Images/General/(#s.TierId).png" alt="Tier #s.TierId"/>
break;
}
</div>
}
</div>
}
}
</div>
</div>
</div>
When I try and run the code it tell me that it cannot find the _GetSearch view, which yes technically is right, but I'm not looking for a view I'm looking for a method in the controller.
Related
So I have tested on a clean project an issue I've been getting, and have done the following code setup for checking if a custom Class object still returns null placed in a List:
VIEW
<div>
<div class="jumbotron">
<h1 class="display-4"><span class="fas fa-user-secret"></span> Babcock Canada - Application Template</h1>
<br />
<div class="alert alert-primary" role="alert">
<span class="fas fa-info-circle"></span>
<span> This is the Babcock Canada MVC Application template for use in developing content-rich web applications.</span>
</div>
<hr class="my-4" />
</div>
<div>
<div class="container-fluid">
#if (!string.IsNullOrEmpty(Model.errorMessage))
{
<div class="alert alert-danger" role="alert">
<span class="fas fa-stop-circle"></span> #Html.DisplayFor(alert => alert.errorMessage)
</div>
}
#if (!string.IsNullOrEmpty(Model.successMessage))
{
<div class="alert alert-success" role="alert">
<span class="fas fa-check-circle"></span> #Html.DisplayFor(alert => alert.successMessage)
</div>
}
<div>
#using (Html.BeginForm("TestAction", "Default", FormMethod.Post))
{
#Html.HiddenFor(m => Model.tester[0].tester)
<button type="submit" class="btn btn-primary">
Submit 1
</button>
}
</div>
<div>
#using (Html.BeginForm("TestAction", "Default", FormMethod.Post))
{
#Html.HiddenFor(m => Model.tester[1].tester)
<button type="submit" class="btn btn-primary">
Submit 2
</button>
}
</div>
</div>
</div>
TestClass.cs
namespace Test.Models
{
public class TestClass
{
public string tester { get; set; }
}
}
MODEL
namespace Test.Models
{
/// <summary>
/// This is the default template model.
/// </summary>
public class DefaultModel : SharedModel
{
public string errorMessage = string.Empty;
public string successMessage = string.Empty;
public List<TestClass> tester { get; set; }
public DefaultModel()
{
}
public void Init()
{
tester = new List<TestClass>
{
new TestClass { tester = "Testing..." },
new TestClass { tester = "Testing2..." }
};
}
}
}
CONTROLLER
[HttpPost]
public ActionResult TestAction(DefaultModel model)
{
return View(model);
}
So the result is that the second one returns NULL in the list, but the first one returns just fine.
In my other project index 0 of a list looped in the same way returns the error: "An item with the same key has already been added."
So what am I doing wrong?
try using the helper Html.Hidden() instead
<div>
#using (Html.BeginForm("TestAction", "Default", FormMethod.Post))
{
#Html.Hidden("tester", Model.tester[0].tester)
<button type="submit" class="btn btn-primary">
Submit 1
</button>
}
</div>
<div>
#using (Html.BeginForm("TestAction", "Default", FormMethod.Post))
{
#Html.Hidden("tester", Model.tester[1].tester)
<button type="submit" class="btn btn-primary">
Submit 2
</button>
}
</div>
Turns out it doesn't work when the form is inside the loop, has to be outside and reference an ID value through the submit button holding the name "ID" and the value of that list item.
Suppose using Html.Hidden() would work, but that isn't what was required for the project.
I'm making a create item page, and in this create item page there is a popup modal table where we can choose the type of UoM that we want. And normally when this form is submitted with all of the fields filled in, it saved the values into the database. But when the form is submitted with one or some or all of the fields not filled in, it supposed to give some error message that the fields are required. But it didn't and it shows this error.
These are my code
ItemController
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Threading.Tasks;
using CRMandOMS.Models;
using CRMandOMS.ViewModels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace CRMandOMS.Controllers
{
public class ItemController : Controller
{
private readonly IItemRepository _itemRepository;
private readonly IUoMRepository _uoMRepository;
public ItemController(IItemRepository itemRepository, IUoMRepository uoMRepository)
{
_itemRepository = itemRepository;
_uoMRepository = uoMRepository;
}
// GET: /<controller>/
public ViewResult Index()
{
var model = _itemRepository.GetAll();
return View(model);
}
public ViewResult Details(Guid? id)
{
Item item = _itemRepository.GetById(id.Value);
return View(item);
}
[HttpGet]
public ViewResult Create()
{
ItemCreateViewModel itemCreateViewModel = new ItemCreateViewModel()
{
UoMs = _uoMRepository.GetAll()
};
return View(itemCreateViewModel);
}
[HttpPost]
public IActionResult Create(ItemCreateViewModel model)
{
if (ModelState.IsValid)
{
Item newItem = new Item
{
Name = model.Name,
Price = model.Price,
UoMId = model.UoMId
};
_itemRepository.Insert(newItem);
return RedirectToAction("Details", new { id = newItem.Id });
}
return View();
}
}
}
Create
#model CRMandOMS.ViewModels.ItemCreateViewModel
#{
ViewData["Title"] = "Item Create";
}
<h2>Item Create</h2>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Item" asp-action="Index">Item</a></li>
<li class="breadcrumb-item active" aria-current="page">Create</li>
</ol>
</nav>
<form enctype="multipart/form-data" asp-controller="Item" asp-action="Create" method="post" class="mt-3">
<div class="form-group row">
<label asp-for="Name" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Name" class="form-control" placeholder="Name" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Price" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Price" class="form-control" placeholder="Price" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="UoMId" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="UoMId" id="uomid" class="form-control" hidden />
<div class="input-group mb-3">
<input id="uomname" type="text" class="form-control" placeholder="UoM" aria-label="UoM" aria-describedby="button-uom" disabled>
<div class="input-group-append">
<button class="btn btn-outline-success" type="button" id="button-uom" data-toggle="modal" data-target="#uoMLookupTableModal">Select UoM</button>
</div>
</div>
<span asp-validation-for="UoMId" class="text-danger"></span>
</div>
</div>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<a asp-controller="Item" asp-action="Index" class="btn btn-light">Back</a>
<button type="submit" class="btn btn-success">Create</button>
</div>
</div>
</form>
#{
await Html.RenderPartialAsync("_UoMLookup");
}
#section scripts {
<script>
$(document).ready(function () {
var uoMTable = $("#uoMTable").DataTable({
"columnDefs": [
{
"targets": [0],
"visible": false
}
],
"order": [[1, "asc"]]
});
$('#uoMTable tbody').on('click', 'tr', function () {
if ($(this).hasClass('table-success')) {
$(this).removeClass('table-success');
}
else {
uoMTable.$('tr.table-success').removeClass('table-success');
$(this).addClass('table-success');
}
});
$("#getUoM").click(function () {
var uomdata = uoMTable.row('.table-success').data();
//alert(uomdata[0]);
$('#uomid').val(uomdata[0]);
//alert(uomdata[1]);
$('#uomname').val(uomdata[1]);
});
});
</script>
}
_UoMLookup
<div class="modal fade" id="uoMLookupTableModal" tabindex="-1" role="dialog" aria-labelledby="uoMLookupTableModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<table id="uoMTable" class="table table-striped table-bordered table-bordered nowrap" style="width:100%">
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
#foreach (UoM uom in Model.UoMs)
{
<tr>
<td class="uom-id">#uom.Id</td>
<td class="uom-name">#uom.Name</td>
<td>#uom.Description</td>
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-dismiss="modal">Cancel</button>
<button id="getUoM" type="button" class="btn btn-success" data-dismiss="modal">Select</button>
</div>
</div>
</div>
</div>
ItemCreateViewModel
using CRMandOMS.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace CRMandOMS.ViewModels
{
public class ItemCreateViewModel
{
[Required]
[MaxLength(100, ErrorMessage = "Name cannot exceed 100 characters")]
public string Name { get; set; }
[Required(ErrorMessage = "{0} is required")]
[Range(1000, 999999999)]
public int Price { get; set; }
[Required]
public Guid UoMId { get; set; }
public IEnumerable<UoM> UoMs { get; set; }
public string PhotoPath { get; set; }
}
}
In the HTTP POST Create method (ItemController) if the model is not valid (so ModelState.IsValid == false) you are not passing a model to your View. Ensure passing a valid model, as shown in the controller methods tutorial.
But when the form is submitted with one or some or all of the fields not filled in, it supposed to give some error message that the fields are required. But it didn't and it shows this error.
You do not have a reference to validation scripts, make sure you have _ValidationScriptsPartial.cshtml in Shared folder, then modify your code:
#section scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script>
//...
</script>
}
For the error on your page, just like other community has said, it is likely that the model state is invalid and it execute return View() without returning any data to create view.
However,your partial view does not allow the Model.UoMs to be null.
In your Create Post action, if the model contains UoMs, you could just use
return View(model)
otherwise ,assign UoMs data to model like what you have done in Create Get action, then return it to view.
You could always use a breakpoint on the Post action to debug the result.
My create button isn't working when clicked on. Can someone please tell me where I went wrong?
I tried a few forums but they haven't solved the issue.
Controller:
using Rentals.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Rentals.Controllers
{
public class GenreController : Controller
{
private ApplicationDbContext db;
public GenreController()
{
db = new ApplicationDbContext();
}
// GET: Genre
public ActionResult Index()
{
return View(db.Genres.ToList());
}
//getaction
public ActionResult Create()
{
return View();
}
//post action to insert data into database
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Genre genre)
{
if (ModelState.IsValid)
{
db.Genres.Add(genre);
db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
protected override void Dispose(bool disposing)
{
db.Dispose();
}
}
}
View (create.cshtml):
#model Rentals.Models.Genre
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
}
<div class="form-horizontal">
<h3> Create new Genre</h3>
<hr />
<div class="form-group">
#Html.LabelFor(m=>m.Name, htmlAttributes: new { #class ="control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(m=>m.Name, new {htmlAttributes = new {#class="form-control"}})
#Html.ValidationMessageFor(m=>m.Name,"", new { #class = "text-danger"})
</div>
</div>
</div>
<div>
<input type="submit" value="Create" class="btn btn-sm btn-success" />
#Html.Partial("_BackToListPartial")
</div>
When I click on the create button it should add to the database. For some reason when I click it, it's not doing anything.
Wrap the form around your HTML.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h3> Create new Genre</h3>
<hr />
<div class="form-group">
#Html.LabelFor(m=>m.Name, htmlAttributes: new { #class ="control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(m=>m.Name, new {htmlAttributes = new {#class="form-control"}})
#Html.ValidationMessageFor(m=>m.Name,"", new { #class = "text-danger"})
</div>
</div>
</div>
<div>
<input type="submit" value="Create" class="btn btn-sm btn-success" />
#Html.Partial("_BackToListPartial")
</div>
}
I've created a page that uses entity framework to retrieve/Display info in the database I've also got create functionality in a partial view on the same page but it doesn't save/insert data.
Here is my Home View:
#model IEnumerable<TerminalHost.Models.buildingInfo>
#{
ViewBag.Title = "Home Page";
}
<h3>We suggest the following:</h3>
<ol class="round">
<li class="one">
<h5>Please begin creating your network structure:</h5> <button id="modal-opener">Add a new building</button>
</li>
<li class="two">
</li>
</ol>
<div class="Container">
<div class="Box1">
#foreach (var item in Model)
{<div>
<h4 class="Heading">#item.buildingName</h4>
<h4 class="Heading">#item.buildingNumber</h4>
<p>#item.buildingDesc1</p>
<p>#item.buildingDesc2</p>
<p>#item.buildingDesc3</p>
</div>
}
</div>
</div>
<div id="Modal" title="Building Details">
#Html.Partial("buildForm", new TerminalHost.Models.buildingInfo())
</div>
Here is my partial View:
#model TerminalHost.Models.buildingInfo
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>buildingInfo</legend>
<div class="editor-label">
#Html.LabelFor(model => model.buildingNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.buildingNumber)
#Html.ValidationMessageFor(model => model.buildingNumber)
</div>
....
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And This is my controller:
public class HomeController : Controller
{
thDB _db = new thDB();
public ActionResult building()
{
var buildingModel = _db.buildings.ToList();//you have to remove the FirstOrDefault() extension method
return View(buildingModel);
}
public ActionResult buildForm()
{
return PartialView();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult buildForm(buildingInfo buildinginfo)
{
if (ModelState.IsValid)
{
_db.buildings.Add(buildinginfo);
_db.SaveChanges();
return RedirectToAction("Index");
}
return PartialView(buildinginfo);
}
protected override void Dispose(bool disposing)
{
if(_db != null)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
I've attempted to replicate the same code as the scaffold template that is created to do the CRUD functions but they are separated out into different views whereas I want them all on one page.
What you need it's to tell your partial view the Action to call.
Could you change this line:
#using (Html.BeginForm())
To
#using (Html.BeginForm("builForm","Home"))
And in your Action:
HttpPost]
[ValidateAntiForgeryToken]
public ActionResult buildForm(buildingInfo buildinginfo)
{
if (ModelState.IsValid)
{
_db.buildings.Add(buildinginfo);
_db.SaveChanges();
return RedirectToAction("Index");
}
return PartialView(buildinginfo);//instead of return this you can redirect to Index so you can see the update. Just a suggestion
}
I have troubles with binding my button to an action. I created a form and when user click "send" button it needs to trigger some action.
Below you can see my cshtml code:
#model Project.Models.MailMessage
<form name="contactForm" method="post" action="" class="form-horizontal" role="form">
<div class="col-lg-8">
<div id="Contact" class="jumbotron contact-form">
<div class="panel-heading">
<h1 class="panel-title">Kontakt</h1>
</div>
<div class="input-group">
<span class="input-group-addon">Imie</span>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control" ,placeholder ="Twoje imię"})
<!--<input type="text" class="form-control" placeholder="Imie" id="inputName" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Nazwisko</span>
#Html.TextBoxFor(model => model.Surname, new { #class = "form-control", placeholder = "Twoje nazwisko" })
<!--<input type="text" class="form-control" placeholder="Nazwisko" id="inputSurname" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Email</span>
#Html.TextBoxFor(model => model.EmailAdress, new { #class = "form-control", placeholder = "Adres email" })
<!--<input type="email" class="form-control" placeholder="Email" id="inputEmail" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Treść<br /> wiadomości</span>
#Html.TextAreaFor(model => model.Name, new { #class = "form-control", placeholder = "Treść wiadomości", id = "inputMessage", name = "inputMessage", rows="4" })
<!--<textarea class="form-control" rows="4" id="inputMessage" name="inputMessage" placeholder="Treść wiadomości..." required="required"></textarea>-->
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-1">
<button type="submit" class="btn btn-default">
Send Message
</button>
</div>
</div>
</div>
</div>
</form>
Here is my Controller:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
// GETL /Search/
public ActionResult Search()
{
return View();
}
public ActionResult Contact()
{
return View();
}
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}
}
I managed to do all this things. All code works. But stucked with I think easies part tof a job. Binding button to call SendMail(MailMessage m) from Controller.
Can anyone suggest me how to do this?
Use Html.BeginForm helper and <input type="submit" value="..." /> within. See an example here. Prefer infrastructure helpers over own HTML code where possible. You probably do not use Antiforgery mechanics to prevent CSRF attacks. It's recommended in post forms, as described in the example.
You have to declare the action of the form.
<form ... action="#Url.Action("SendMail","Home")" ...>
Try this:
SendMail.cshtml
#model Project.Models.MailMessage
<form name="contactForm" method="post" action="" class="form-horizontal" role="form">
<div class="col-lg-8">
<div id="Contact" class="jumbotron contact-form">
<div class="panel-heading">
<h1 class="panel-title">Kontakt</h1>
</div>
<div class="input-group">
<span class="input-group-addon">Imie</span>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control" ,placeholder ="Twoje imię"})
<!--<input type="text" class="form-control" placeholder="Imie" id="inputName" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Nazwisko</span>
#Html.TextBoxFor(model => model.Surname, new { #class = "form-control", placeholder = "Twoje nazwisko" })
<!--<input type="text" class="form-control" placeholder="Nazwisko" id="inputSurname" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Email</span>
#Html.TextBoxFor(model => model.EmailAdress, new { #class = "form-control", placeholder = "Adres email" })
<!--<input type="email" class="form-control" placeholder="Email" id="inputEmail" required="required">-->
</div>
<div class="input-group">
<span class="input-group-addon">Treść<br /> wiadomości</span>
#Html.TextAreaFor(model => model.Name, new { #class = "form-control", placeholder = "Treść wiadomości", id = "inputMessage", name = "inputMessage", rows="4" })
<!--<textarea class="form-control" rows="4" id="inputMessage" name="inputMessage" placeholder="Treść wiadomości..." required="required"></textarea>-->
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-1">
<button type="submit" class="btn btn-default">
Send Message
</button>
</div>
</div>
</div>
</div>
</form>
Here you controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
// GETL /Search/
public ActionResult Search()
{
return View();
}
public ActionResult Contact()
{
return View();
}
[HttpGet]
public ActionResult SendMail(MailMessage m)
{
return View();
}
[HttpPost]
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}
}
When you click on button it call [HttpPost] Method in you controller. It is necessary to mention [HttpPost]
just change your method
[HttpPost]
public ActionResult SendMail(MailMessage m)
{
return RedirectToAction("Contact");
}