I am having this issue where I have a form in a partialview but when validating it jumps out of the parent view and appears on its own (having the submit action url).
Also I tried with Render.Action, where validation does not fire at all.
I am using ASP.NET MVC 2 RC and need the server-side validation to work, using the built in validation. Anyone got any suggestions?
Thanks
Code Partial View:
<%=Html.ValidationSummary() %>
<% using (Html.BeginForm("Edit", "Category", FormMethod.Post))
{%>
<fieldset>
<legend>Edit category</legend>
<p>
<label for="CategoryName">Category name:</label>
<%= Html.TextBox("CategoryName", Model.CategoryName)%>
<%= Html.ValidationMessage("CategoryName", "*")%>
</p>
<p class="submit">
<input type="submit" value="Edit" />
<%=Html.AntiForgeryToken()%>
<%= Html.Hidden("CatId", Model.Id)%>
</p>
</fieldset>
<% }
Model Property:
[Required(ErrorMessage="Required")]
public string CategoryName { get; set; }
Edit Action:
[ValidateAntiForgeryToken]
[HttpPost()]
public ActionResult Edit(int catId, CategoryPageViewModel categoryModel)
{
if (ModelState.IsValid)
{
//TODO
}
return View("list", categoryModel);
}
Does your main view also display category? You're passing "list" a categoryModel. Is this enough for the main view as well as the partial view.
Related
I have this form in my view which leads me to some action in the controller. The thing is I don't know how to pass parameters to the action method.
<form class="full-search" asp-controller="Movies" asp-action="Search">
<input type="search" name="searchmovie" placeholder="Search..." class="search-form">
<select name="option" form="">
<option name="option" value="category1">category 1</option>
<option name="option" value="category2">category 2</option>
<option name="option" value="category3">category 3</option>
</select>
<i class="fas fa-caret-down"></i>
<input type="submit" name="" class="submit-full-search">
<div class="search-btn-submit">
<img src="~/img/search.svg">
</div>
</form>
And this is my controller:
[HttpGet("searchmoview/{option?}/{searchmovie}")]
public IActionResult Search(string option, string searchmovie)
{
//perform some search based on the filters
return View("Search", data);
}
But when I run my code, when I click on search the url looks like this:
https://localhost:33590/Information/Search
Instead of like this:
https://localhost:44320/seachmovie/category1/{searchString}
Any idea guys on how can I pass the parameters?
Long story short - there is no out of the box way of mapping form values to a route.
The best way to pass values back to your mvc controllers is to have a view model.
Create a search view model.
//View Model
public class SearchViewModel{
public string Query {get;set;}
public string Category {get;set;}
}
In your controller you'll want to pass this down to your view or partial view.
Use "ActionResult" in .NET and "IActionResult" in .Net Core
//Controller
public class SearchController{
[HttpGet]
public ActionResult SearchBox(){
return View();
}
[HttpPost]
public ActionResult SearchBox(SearchViewModel model){
//model is now populated with your values from your form.
//ex: model.Query
return View();
}
}
Create an enum for your categories, there is many other ways to do this but this one is the simplest.
//Enum
public enum Categories
{
Category1,
Category2
}
Now in your razor view bind your view model and you're good to go.
//Razor View
#model SearchViewModel
#using (Html.BeginForm("SearchBox", "Search", FormMethod.Post))
{
#Html.TextBoxFor(x => x.Query, new { #class = "search-form"})
#Html.DropDownListFor(x => x.Catergory,
new SelectList(Enum.GetValues(typeof(Categories))),
"Select Category", new { #class= "example-class"})
<i class="fas fa-caret-down"></i>
<input type="submit" name="" class="submit-full-search">
<div class="search-btn-submit">
<img src="~/img/search.svg">
</div>
}
If you want the form values to be posted to your url you can change it to FormMethod.Get
//Razor View
#model SearchViewModel
#using (Html.BeginForm("SearchBox", "Search", FormMethod.Get))
{
#Html.TextBoxFor(x => x.Query, new { #class = "search-form"})
#Html.DropDownListFor(x => x.Catergory,
new SelectList(Enum.GetValues(typeof(Categories))),
"Select Category", new { #class= "example-class"})
<i class="fas fa-caret-down"></i>
<input type="submit" name="" class="submit-full-search">
<div class="search-btn-submit">
<img src="~/img/search.svg">
</div>
}
If you change it to get, you'll also have to change your controller to expect these in your get method. You can also just bind the model and MVC will map the parameters back into the model for you automatically.
public class SearchController{
[HttpGet]
public ActionResult SearchBox(SearchViewModel model){
//if the model values are in the URL "model" will be populated, else it will be null.
return View();
}
}
You can't. That's not how things work. A form will by default send a POST request, in which case inputs in the form are sent as part of the request body (i.e. not the URL). You can set the method to GET, instead, but then the input values will be sent as part of the query string (i.e. ?foo=bar), not as part of your path, as you're looking for.
The only way to remotely achieve what you want is to use JavaScript to manipulate the form's action based on things like the category select box changing. You'd bind to the change event of that element, and then you'd alter the form element's action attribute in some way.
I'm trying to implement a basic search page in the web app I'm developing. Right now the page looks like this
When a user enters a last name, the controller gets called to search the backend Microsoft SQL Server database for all accounts with that Last name
Right now the HTML form looks like this
#using (Html.BeginForm("SearchAct", "HomeController", FormMethod.Post))
{
<form>
<div>
Last Name:<br>
<input type="text" id="nameToFind">
<input type="button" id="submitId" value="submit" />
</div>
</form>
}
It's supposed to call this controller
[HttpPost]
public void SearchAct()
{
Console.WriteLine();
}
which will eventually execute the search and then put the results on the page. However, I can't get the controller to be called. I set a break point on the WriteLine so I know its never getting there and I don't know what I'm doing wrong
Add name attribute to your text box. Form collection build based on only name attributes.
Change button type to submit, then it will post your form to controller.
#using (Html.BeginForm("SearchAct", "Home", FormMethod.Post))
{
<div>
Last Name:<br>
<input type="text" id="nameToFind" name="nameToFind">
<input type="submit" id="submitId" value="submit" />
</div>
}
#{
if(ViewBag.SearchKey != null)
{
<span>
Search Key: #ViewBag.SearchKey
</span>
}
}
Instead on Console.WriteLine() use ViewBag to send your required data back to view
Refer below actions
//Get Action for rendering view
public ActionResult SearchAct()
{
return View();
}
[HttpPost]
public ActionResult SearchAct(string nameToFind)
{
ViewBag.SearchKey = nameToFind;
return View();
}
Action parameter name and text box name attribute value must be same otherwise it will null
If your form contains multiple text box then read all input values form FromCollection or Request
[HttpPost]
public ActionResult SearchAct(FormCollection form)
{
ViewBag.SearchKey = form["nameToFind"];
return View();
}
correct your form HomeController should be just Home
#using (Html.BeginForm("SearchAct", "Home", FormMethod.Post))
{
<form>
<div>
Last Name:<br>
<input type="text" id="nameToFind">
<input type="button" id="submitId" value="submit" />
</div>
</form>
}
controller should accept the input parameter for your filter
[HttpPost]
public void SearchAct(string nameToFind)
{
// filter snomething
Console.WriteLine(nameToFind);
}
First: To create a form via using razor syntax:
#using (Html.BeginForm("SearchAct", "HomeController", FormMethod.Post))
{
}
That would generate a form like this:
<form method="post" action="/HomeController/SearchAct">
</form>
So, no need to create a nested form inside that.
#using (Html.BeginForm("SearchAct", "HomeController", FormMethod.Post))
{
<form> // <- here
<div>
Last Name:<br>
<input type="text" id="nameToFind">
<input type="button" id="submitId" value="submit" />
</div>
</form> // <- here
}
Second: HomeController would match the controller what the full name is HomeControllerController.
So, if you want to hit Home controller, remove Controller from HomeController in #using (Html.BeginForm("SearchAct", "HomeController", FormMethod.Post)) {}
Thirth: if you want to catch nameToFind, you can try:
[HttpPost]
public void SearchAct(string nameToFind)
{
Console.WriteLine();
}
Hope this help!
first of all we dont need to two form tag and you dont need to add controller suffix. remve that:
#using (Html.BeginForm("SearchAct", "Home", FormMethod.Post))
{
<div>
Last Name:<br>
<input type="text" id="nameToFind" name="nameToFind">
<input type="button" id="submitId" value="submit" />
</div>
}
Secondly if you need to search you need to add paramater same as the name of input type text :
[HttpPost]
public void SearchAct(string nameToFind)
{
Console.WriteLine();
}
I am entirely new to asp.net mvc and this is my first sample project that I need to show one textbox in one view when the user entered a value in that textbox, I need to display that value in label in another view.
for that I have done like this ..
this is my controller class
public class TextBoxController : Controller
{
//
// GET: /TextBox/
public ActionResult Index()
{
return View();
}
}
and this is my model class
namespace MvcTestApplication.Models
{
public class TextboxModel
{
[Required]
[Display(Name= "Textbox1")]
public string EnteredValue { get; set; }
}
}
and this is my view
#model MvcTestApplication.Models.TextboxModel
#{
ViewBag.Title = "TextboxView";
}
<h2>TextboxView</h2>
#using (Html.BeginForm())
{
<div>
<fieldset>
<legend>Enter Textbox Value</legend>
<div class ="editor-label">
#Html.LabelFor(m => m.EnteredValue)
</div>
<div class="editor-field">
#Html.TextBoxFor(m=>m.EnteredValue)
</div>
<p>
<input type="submit" value="Submit Value" />
</p>
</fieldset>
</div>
}
I am not able to see any textbox and any button on page and I am getting error like
HTTP:404 : Resource Cannot be found
I am using visual studio 2012 and mvc4..
would any pls suggest any idea on this one ..
Many thanks..
RE-WRITTEN
In simple terms, to access a page on ASP.NET MVC, you should point the URL to its controller name. In this case, TextBox:
localhost:2234/TextBox/TextBox
Also, you forgot to add an ActionResult for this new view. When you're loading the page, it's going through the Index one, which is empty.
The final code should look like this:
Controller
public class TextBoxController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult TextBox(MvcApplication1.Models.TextBoxModel model)
{
return View(model);
}
}
Model
public class TextBoxModel
{
[Required]
[Display(Name = "Textbox1")]
public string EnteredValue { get; set; }
}
Razor View (Index)
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Razor View (TextBox)
#model MvcApplication1.Models.TextBoxModel
#{
ViewBag.Title = "TextBox";
}
<h2>TextBox</h2>
#using (Html.BeginForm())
{
<div>
<fieldset>
<legend>Enter Textbox Value</legend>
<div class ="editor-label">
#Html.LabelFor(m => m.EnteredValue)
</div>
<div class="editor-field">
#Html.TextBoxFor(m=>m.EnteredValue)
</div>
<p>
<input type="submit" value="Submit Value" />
</p>
</fieldset>
</div>
}
Make sure that you have registered the URL via route config.
Find more about asp.net routing here
UPDATE:
Make sure that file name of your view is Index.cshtml since your controller doesn't specify any return view names.
I'm trying to implement what this answer suggests but without storing the display name in my model code, so I believe it's a separate question.
I have an MVC view
<%# Page Language="C#" MasterPageFile="PathToMaster" Inherits="System.Web.Mvc.ViewPage<ModelData>" %>
and a model:
public class ModelData {
public bool Option1 { get; set; }
}
and I have a .aspx with HTML markup for a form that contains a checkbox:
<label for="MyCheckbox">Your choice</label>
<%= Html.CheckBoxFor(Model=>Model.Option1, new { id="Option1", #class="checkbox", onchange="return myValidation();", name="MyCheckbox", value="Option one" } ) %>
which when it is compiled yields this HTML:
<label for="MyCheckbox">Your choice</label>
<input class="checkbox" id="Option1" name="Option1" onchange="return myValidation();" type="checkbox" value="Option one" /><input name="Option1" type="hidden" value="false" />
and whenever I check the checkbox and submit the form the controller-action
class MyController : Controller {
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult RequestStuff( ModelData data )
{
}
}
receives data where Option1 is false.
What am I doing wrong? How do I make the checkbox map to the model member?
Since you said changing the alias in the helper expression didn't cut it, I took the time to prepare the MVC2 test project, here's how it looks:
MyModel.cs:
namespace TestAppMVC2.Models
{
public class MyModel
{
public bool Option1 { get; set; }
}
}
Controller's actions:
public ActionResult MyAction()
{
var viewModel = new MyModel();
return View(viewModel);
}
[HttpPost]
public ActionResult MyAction(MyModel viewModel)
{
bool option = viewModel.Option1;
return View();
}
The view (MyAction.aspx):
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TestAppMVC2.Models.MyModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
MyAction
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>MyAction</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Option1) %>
</div>
<div class="editor-field">
<%: Html.CheckBoxFor(model => model.Option1) %>
<%: Html.ValidationMessageFor(model => model.Option1) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
Looks like this:
And the result after checking the checkbox:
By the way, the View was generated entirely (well, almost entirely, I changed TextBoxFor to CheckBoxFor) by Add View -> Strongly Typed View for the MyModel class and template: Edit.
So it looks like the binding above should be OK. Try this and then you can fiddle with custom options on checkboxes. :)
Like I wrote in the other answer, the idea is essentially the same, only in MVC3 the Razor syntax looks a bit cleaner. But that's about it when it comes to differences. :)
In your line:
<%= Html.CheckBoxFor(Model=>Model.Option1, new { id="Option1", #class="checkbox", onchange="return myValidation();", name="MyCheckbox", value="Option one" } ) %>
Replace Model with another alias, i.e. m. So it looks like:
<%= Html.CheckBoxFor(m=>m.Option1, new { id="Option1", #class="checkbox", onchange="return myValidation();", name="MyCheckbox", value="Option one" } ) %>
You referred to the Model directly where CheckBoxFor takes an an HTML helper instance.
I believe the following maybe appropriate to help you understand further:
MVC HTML Helpers and Lambda Expressions
I'm trying to create a view that contains a list of checkboxes that is dynamically created from a database, and then retrieve the list of selected ones when the form is posted back.
My EF model contains a class:
public class ItemIWouldLikeACheckboxFor {
public int Id { get; set; }
public string Description { get; set; }
}
I have a view model that contains a list of these:
public class PageViewModel {
// various other properties
public List<ItemIWouldLikeACheckboxFor> checkboxList { get; set; }
}
My controller get method:
public ActionResult Create() {
var viewModel = new PageViewModel();
viewModel.checkboxList = db.ItemIWouldLikeACheckboxFors.ToList();
return View(viewModel);
}
My view:
<% using (Html.BeginForm()) { %>
<%-- other stuff here... %>
<% foreach (var item in checkboxList) { %>
<%: Html.CheckBox( <!-- what exactly ?????? -->) %>
<% } %>
<%-- other stuff here...%>
<input type="submit" />
<% } %>
My controller post method:
[HttpPost]
public ActionResult Create(PageViewModel viewModel) {
// do stuff with other fields
// I would like to do something like:
foreach (var item in selectedCheckBoxes) {
// do stuff
}
}
I can't seem to get it to work. My basic questions are mixed in as comments in the code snippets, but to recap:
Is my view model OK? (do I need to add anything to capture the selected ones as opposed to simply the list to display?)
What exactly should I put in the view to render each check box?
How do I access the selected checkboxes in the controller after the post?
Have you seen: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx?
We basically wrote our own control to render the HTML like
<label for="Products"> Select Products </label>
<ul class="checkBoxList">
<li>
<input type="hidden" value="0" name="Products.Index">
<input type="checkbox" value="3424" name="Products[0].Id" id="Products0">
<label for="Products0">iPod touch 3rd Generation</label>
</li>
<li>
<input type="hidden" value="1" name="Products.Index">
<input type="checkbox" value="3123" name="Products[1].Id" id="Products1">
<label for="Products1">Creative Zen</label>
</li>
</ul>
</div>
Model Looks Ok, we wrote a custom helper, so our aspx pages look like:
<%= Html.DropDownFor(m=>m.products) %>
If you follow phil haacks post, your model should automatically bind in your controller.
Also a good answer in this question: CheckBoxList multiple selections: difficulty in model bind back
It has a solution that uses a custom Editor Template.