I have created a person register form. In this form I have added one partial view which shows list of persons. I have added a paging on this form. Now I want to implement search functionality.
My form looks like following
Here I want to implement search functionality. but the issue is I have two buttons on a form i.e. Create and search. when I click on search button it gives me required field validation of form register.cshtml.
Here is my code for register.cshtml
#model WebLess.Models.PersonModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.firstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.firstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.firstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.lastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.lastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
<div class="form-group">
#if (ViewBag.Message != null)
{
<span class="text-success">#ViewBag.Message</span>
}
</div>
<div class="form-group">
#Html.Partial("list", Model.listOfPerson)
</div>
</div>
}
Here is my list.cshtml.
#model PagedList.IPagedList<WebLess.Models.PersonModel>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#using (Html.BeginForm("Register", "Person", FormMethod.Get))
{
<p>
Find by name: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}
<table class="table">
<tr>
<th>
First name
</th>
<th>
Last name
</th>
<th>
E-mail Address
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.firstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.lastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
</tr>
}
</table>
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Register",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
How can I implement search functionality?
You can move the list partial view outside of the creation form, then put the search functionality into its own form inside the list partial view (they're completely separate anyway, so should be separate). This should then achieve what you're looking for.
Nesting of forms is not allowed and may result in an undefined behavior between browsers.
Use two seperate form instead of nested form
like steve says "move the list partial view outside of the creation form" would result into two separate form instead of one form inside another form
like
#using (Html.BeginForm())
{
}
#using (Html.BeginForm("Register", "Person", FormMethod.Get))
{
}
instead of (a form in a form is not allowed )
#using (Html.BeginForm())
{
#using (Html.BeginForm("Register", "Person", FormMethod.Get))
{
}
}
Related
The popup code works just fine when I create it on the other view pages, it only throws an error on the index page, I'm having an issue with the model. I'm new to ASP.NET MVC 5 and Entity Framework 6. Any guidance will be most appreciated.
This is my code:
#model IEnumerable<LogInTest1.Models.Credentials>
I want to create a popup here instead of redirecting it to the create page.
<p>
#Html.ActionLink("Create New", "Create")
</p>
Button code:
<button class="btn btn-default" onclick="AddData()">Click to Create »</button>
<script>
function AddData() {
$("#MyModal").modal();
}
</script>
Popup code:
<div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
#*#model LogInTest1.Models.Credentials*#
#*#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Credentials</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.userName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.userName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.userName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}*#
#*}*#
</div>
</div>
</div>
</div>
Table code at index view:
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.userName)
</th>
<th>
#Html.DisplayNameFor(model => model.password)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.userName)
</td>
<td>
#Html.DisplayFor(modelItem => item.password)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.empId }) |
#Html.ActionLink("Details", "Details", new { id = item.empId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.empId })
</td>
</tr>
}
</table>
Simply, you can use an action link like this:
Create New
Your Index view having Model list but your popup using single model so you have to create the object to your popup model#{var createModel = new LogInTest1.Models.Credentials()} then your all poup codes should look like this #Html.LabelFor(cmodel => createModel.userName, htmlAttributes: new { #class = "control-label col-md-2" })
I´m working on ASP .NET MVC 5 application and now I´m implementing newsletter functionality. I have master (parent view) with all stuff and on this view there is also box with input field for email and submit button. After click on this button, controller method insert this e-mail to subscribers tab. I´ve got GET/POST method and PartialView for this Newsletter (all newsletter´s code is in separate area).
Everything works fine, there is only one problem. On master page I have another submit button (for submitting search string) so everytime after submitting search string, code also submit newsletter form.
Is there any solution to separate this two submit buttons and way to not refresh whole page after submit newsletter (PartialView) form?
Here is my Newsletter PartialView called _SignIn
#using (Html.BeginForm())
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.email, htmlAttributes: new {#class = "control-label col-md-12", style="text-align: left; padding-left: 30px;"})
<div class="col-md-12" align="center">
#Html.EditorFor(model => model.email, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.email, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.NewsletterType, htmlAttributes: new { #class = "control-label col-md-12", style = "text-align: left; padding-left: 30px;" })
<br />
<div class="col-md-12" align="center">
#Html.EnumDropDownListFor(model => model.NewsletterType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.NewsletterType, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-10" style="padding-bottom: 10px;">
<input type="submit" value="Prihlásiť" class="btn btn-success" />
</div>
</div>
</div>
Thank you for any response!
You will only achieve this using ajax calls, with that, you do not need to refresh the whole page.
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.email, htmlAttributes: new {#class = "control-label col-md-12", style="text-align: left; padding-left: 30px;"})
<div class="col-md-12" align="center">
#Html.EditorFor(model => model.email, new {htmlAttributes = new {#class = "form-control", id = "emailTxt"}})
#Html.ValidationMessageFor(model => model.email, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.NewsletterType, htmlAttributes: new { #class = "control-label col-md-12", style = "text-align: left; padding-left: 30px;" })
<br />
<div class="col-md-12" align="center">
#Html.EnumDropDownListFor(model => model.NewsletterType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.NewsletterType, "", new { #class = "text-danger", id = "ddlType" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-10" style="padding-bottom: 10px;">
<button type="button" class="btn btn-success btn-newsletter"></button>
</div>
</div>
</div>
<script>
$(function(){
var model = {
email: $('.emailTxt').text();
NewsletterType: $('.ddlType :selected').text();
}
$(.btn-newsletter).click(function(){
$.ajax({
url: url,
type: 'POST',
data: model,
beforeSend: function(xhr){xhr.setRequestHeader('__RequestVerificationToken', $('body').find('input[name="__RequestVerificationToken"]'));},
statusCode: {
200: function (data) { success(data); },
500: function (erro) { error(erro); }
}
});
});
});
</script>
Add name attribute to your buttons, and use the value in your controller to distinguish which button was invoked.
<button type="submit" id="btnSave" name="Command" value="Save">Save</button>
<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
public ActionResult YourAction(Model model, string Command)
{
if(Command == "Save") {}
}
Refer to Handling multiple submit buttons for more info.
To prevent the full postback (refresh) you could use AJAX
You have to have two separate forms to handle each submission or handle it through some form of Javascript. I'd suggest using 2 separate forms. Put the search string submission in the parent view since it should be on all the pages and close the form. Then you can render your partial view for the newsletter subscription with a form inside of it.
Basically:
Parent view
...
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<!-- Search string input field and submit button -->
...
</div>
}
<div>
#Html.RenderPartial("_SignUp")
</div>
...
_SignUp Partial view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<!-- Subscriber email input and submit -->
...
</div>
}
I have the following view:
#model GRCWebApp.ViewModels.NewClubInterestsViewModel
#{
ViewBag.Title = "Add Club Interests";
}
<div class="col-md-10 col-offset-md-1">
<h2 class ="text-success">Add Club Interests for #Html.DisplayFor(model => model.Name)</h2>
</div>
#using (Html.BeginForm("NewInterests", "Club", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
<div class="row">
<div class="col-md-8">
<div class="well bs-component">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(x => Model.ClubId)
<div class="form-group">
<div class="col-md-10 col-md-offset-1">
<h3>Tick the areas your club is interested/runs events in</h3>
</div>
</div>
<div class="col-md-offset-1">
#for (int i = 0; i < Model.ClubTypeInterests.Count(); i++)
{
<div>
#Html.HiddenFor(x => Model.ClubTypeInterests[i].InterestId)
#Html.CheckBoxFor(x => Model.ClubTypeInterests[i].selected)
#Html.LabelFor(x => Model.ClubTypeInterests[i].InterestName, Model.ClubTypeInterests[i].InterestName)
</div>
}
</div>
<div class="form-group">
<div class="row">
<div class="col-md-offset-1 col-md-12">
<input type="submit" name="Submit" value="Next" class="btn btn-success btn-lg" /> to setup Online membership
<input type="submit" name="Submit" value="Complete" class="btn btn-warning btn-sm" /> to just provide online event entries
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
#using (Html.BeginForm("AddInterest", "Club"))
{
#Html.AntiForgeryToken()
<hr />
<div class="row">
<div class="col-md-8">
<div class="well bs-component">
<div class="form-group">
<div class="col-md-12 col-md-offset-1">
<h3>Not listed? - Add extras here</h3>
</div>
</div>
#Html.HiddenFor(model => model.ClubTypeId)
#Html.HiddenFor(model => model.ClubId)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-inline">
<div class="form-group">
<div class="row col-md-offset-1 col-md-11">
<div class="col-md-4">
#Html.LabelFor(model => model.InterestName, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.InterestName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.InterestName, "", new { #class = "text-danger" })
</div>
<div class="col-md-5">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
<input type="submit" value="Add" class="btn btn-info" style="margin-top: 22px" />
</div>
</div>
</div>
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Overtime the page loads the Validation message shows for InterestName in the second form AddInterest.
The Get method for the whole form is:
[HttpGet]
public ActionResult NewInterests(NewClubInterestsViewModel model, int id)
{
//Find the Club and then pass its id to the ViewModel
var club = db.Clubs.Find(id);
//model.ClubId = club.ClubId ;
//Interests List
IEnumerable<Interest> allExistingInterests;
//Generate a list of the interests that apply to that type of club
using (ApplicationDbContext context = new ApplicationDbContext())
{
allExistingInterests = context.Interests
.Where(s => s.ClubTypeId == club.ClubTypeId)
.OrderBy(s => s.InterestName)
.ToList();
}
IEnumerable<int> clubInterestIds = club.ClubInterests.Select(x => x.InterestId).ToList();
//Generate the ViewModel with the appropriate Interests
var viewModel = new NewClubInterestsViewModel
{
ClubId = club.ClubId,
Name = club.Name,
ClubTypeId = club.ClubTypeId,
ClubTypeInterests =
allExistingInterests.Select(
x => new ClubInterestsViewModel { InterestId = x.InterestId, InterestName = x.InterestName, selected = clubInterestIds.Contains(x.InterestId) }).ToArray()
};
return View(viewModel);
}
What do I need to do to stop the validation message showing on load?
Remove the NewClubInterestsViewModel model parameter from your GET method. It should be just
public ActionResult NewInterests(int id)
The first step in the model binding process is that instances of your parameters are initialized and then its properties are set based on form values, route values, query string values etc. In your case there are no values to set, so the properties of your model are their defaults, but because you have validation attributes on your properties, validation fails and errors are added to ModelState which are then displayed in the view.
I am creating a page in Asp.Net MVC where a user can upload a file, along with details about the file from textboxes.
For this I use a viewmodel, and a very simple method configuration. The page is populated correctly by the [Get] Method, and the user can choose the file and enter the details, but once the 'Submit' button is clicked, and the [Post] method is called, the viewmodel is completely null.
I have done my research on this and have tried:
adding enctype="multipart/form-data"
simply using the file as a separate parameter
To no avail.
Here is my controller methods:
public ActionResult FileComment(int id)
{
//set up [get] view
return View("FileComment", obj);
}
//THIS METHOD's VIEWMODEL ALWAYS NULL
[HttpPost]
public ActionResult FileComment(CalibrationCommentViewModel file)
{
//save file to database
return View("Edit", new { id = file.id });
}
Here is part of my view:
#using (Html.BeginForm("FileComment", "Calibration", FormMethod.Post, new { enctype = "multipart/form-data", #data_ajax = "false" }))
{
#Html.HiddenFor(m => m.ID)
<div class="container">
<h4>Add File for #Model.ID</h4>
<hr />
<div class="row">
<div class="col-md-1">g
#Html.LabelFor(model => model.file, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-2">
#Html.TextBoxFor(model => model.file, new { type = "file" })
</div>
<div class="col-md-9"></div>
</div>
<br />
<div class="row">
<div class="col-md-1">
#Html.LabelFor(model => model.attachmentType, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-2">
#Html.DropDownListFor(model => model.attachmentType, Model.attachTypeList, new { #class = "form-control" })
</div>
<div class="col-md-9"></div>
</div>
<br />
<div class="row">
<div class="col-md-1">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-2">
#Html.EditorFor(model => model.Date)
</div>
<div class="col-md-9"></div>
</div>
<br />
<div class="row">
<div class="col-md-1">
#Html.LabelFor(model => model.description, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-2">
#Html.TextAreaFor(model => model.description, new { cols=35, #rows=3})
</div>
<div class="col-md-9"></div>
</div>
<br />
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-2">
<button type="submit" onclick="JavascriptFunction()">Add to #Model.ID</button>
</div>
<div class="col-md-9"></div>
</div>
</div>
}
Change
public ActionResult FileComment(CalibrationCommentViewModel file)
to
public ActionResult FileComment(CalibrationCommentViewModel model)
your view has no reference to view model at the top the view something like this
#model Nameofyourproject.Models.CalibrationCommentViewModel
I have a form that uses partialviews to load the different sections. When the information is filled out I would like it to show up on a final partialview to give a confirmation page before submission. How do I grab the information entered on one partialview and display it for submit on the final?
My partialview code looks like this:
#using (Ajax.BeginForm("PrimaryApplicant", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "step3", OnSuccess = "showStep3" }))
{
<h4>Primary Applicant Information</h4>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<hr/>
<div class="form-group">
#Html.LabelFor(m => m.FirstName, new { #class = "col-md-3 control-label" })
<div class="col-md-9">
<div class="col-md-4">
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control", placeholder = "First Name" })
</div>
<div class="col-md-4">
#Html.TextBoxFor(m => m.MiddleName, new { #class = "form-control", placeholder = "Middle Name" })
</div>
<div class="col-md-4">
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control", placeholder = "Last Name" })
</div>
#Html.ValidationMessageFor(m => m.FirstName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.SSN, new { #class = "col-md-3 control-label" })
<div class="col-md-9">
<div class="col-md-4">
#Html.TextBoxFor(m => m.SSN, new { #class = "form-control", placeholder = "Social Security Number" })
#Html.ValidationMessageFor(m => m.SSN)
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.DOB, new { #class = "col-md-3 control-label" })
<div class="col-md-9">
<div class="col-md-4">
#Html.TextBoxFor(m => m.DOB, new { #class = "form-control", type = "date", placeholder = "Date of Birth" })
#Html.ValidationMessageFor(m => m.DOB)
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-3 control-label" })
<div class="col-md-9">
<div class="col-md-4">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", type = "email", placeholder="Email Address" })
</div>
#Html.ValidationMessageFor(m => m.Email)
</div>
</div>
I'm using models to create the input fields and all of its variables. After a user fills out the inputs on one partial view and hits continue it opens the next partialview. Once the form is filled out how would I display a final confirmation page echoing the values they input?
Have a view model per view.
When the next button is clicked submit the form to the current pages' action method.
Store the form data/view model in the user's current session for retrieving later, then display the next view.
repeat step 1 and 2 if necessary.
Retrieve all the data from the session and combine them to your final viewmodel then display your final confirmation page.