Multiple submit buttons from multiple views ASP .NET MVC5 - c#

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>
}

Related

Data parsing from Model to Partial view error ASP.NET MVC

In my Application, In EDIT view I want to call data from the database and fill into the partial view that have sent through to the database when creates the request using same partial view . Currently my code I have written like below. But what happens is, If there is 4 records, It will generate 4 line, but there is no data there. All comes as empty.
<ul id="RequItms" style="list-style-type: none">
#if (Model != null && Model.GeneralItmsList != null)
{
foreach (var item in Model.GeneralItmsList)
{
Html.RenderAction("GeneralItmsPartialView", "AppRequests", Model.GeneralItmsList.ToList());
}
}
</ul>
Here is the view. This is the view I'm currently getting from the above code.
But this is the way it should load in that empty fields.
I have checked in the Model.GeneralItemsList There is shows the data, But I think when parsing it to the partial view must be the error occurs.
Here is the partial view code looks like.
#model Asp_PASMVC.Models.GeneralItms
#using Asp_PASMVC.Infrastructure
<li style="padding-bottom:15px">
#using (Html.BeginCollectionItem("GeneralItmsList"))
{
#Html.HiddenFor(model => model.TempID)
<div class="form-horizontal" id="quickForm" novalidate="novalidate">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-md-5 col-sm-6">
<div class="form-group">
Select Item Description
<div class="col-md-10">
#Html.EditorFor(model => model.Attachment_Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Attachment_Description, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="form-group">
Attachment Amount
<div class="col-md-10">
<div class="input-group-prepend">
<span class="input-group-text">Rs.</span>
#Html.EditorFor(model => model.Attachment_Amount, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.Attachment_Amount, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="form-group">
Attachment
<div class="col-md-10">
<input type="file" name="ImageData#(Model.TempID.ToString())" id="ImageData#(Model.TempID.ToString())" multiple="multiple" data-id="Img#(Model.TempID.ToString())" onchange="checkImage(this)" />
#Html.ValidationMessageFor(model => model.Attachment, "", new { #class = "text-danger" })
</div>
</div>
<img id="Img#(Model.TempID.ToString())" src="" alt="" width="100" height="100" class="ml-1" />
</div>
<button type="button" class="btn btn-danger" onclick="$(this).parent().remove();">Remove</button>
</div>
</div>
}
</li>
I hope that I have explained this question properly. Thanks for the support.

ASP.NET MVC - Using a Form in a Bootstrap Modal to call an Action from a Controller

I have a Form that creates an entry into my database. I am trying to add an additional form via a modal that will allow the user to populate the first form by searching a property on the webservice.
What I need is for when the user types hits search in the modal it will call an action on controller that then runs my web service client that then returns a list of appropriate information. I then want this list displayed as a table on the page. The user can then select which search result they want to use to which will then populate the original form. I think I can figure most of this out but wasnt sure of the best way to kick off the search from the modal. Code is as follows.
View
#model *******
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#Search">Populate From Service</button>
<!-- Modal -->
<div id="Search" 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 By Property</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<p>blah blah blah</p>
<div class="form-group">
<label for="API14" class="control-label col-md-2">API</label>
<div class ="col-md-10">
<input type="text" class="form-control" id="API14" aria-describedby="API14" placeholder="Enter API">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Search" class="btn btn-success" />
<input type="button" value="Close" data-dismiss="modal" class="btn btn-danger" />
</div>
</div>
</div>
</div>
</div>
</div>
#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.API14, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.API14, new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(model => model.API14, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PROP_NO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PROP_NO, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PROP_NO, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PROP_NM, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PROP_NM, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PROP_NM, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ENTITY, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10 ">
#Html.EditorFor(model => model.ENTITY, new { htmlAttributes = new { #class = "form-control" } } )
#Html.ValidationMessageFor(model => model.ENTITY, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PROD_ZONE_NM, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PROD_ZONE_NM, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PROD_ZONE_NM, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LEASE_NAME, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LEASE_NAME, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LEASE_NAME, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.WELL_NO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.WELL_NO, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.WELL_NO, "", 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-success" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
You could divide your issue into two steps.
Step 1: "What I need is for when the user types hits search in the modal it will call an action on controller that then runs my web service client that then returns a list of appropriate information. I then want this list displayed as a table on the page."
Add the following to your scripts section:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$('#submitModal').click(function () {
var data = {
API14: $('#API14').val()
}
$.ajax({
url: '/Default/SearchByProperty',
data: data
}).success(function (html) {
$('#API14List').html(html);
$('#Search').modal('toggle');
});
});
});
</script>
}
This is a simple ajax call that takes the value from you modal input and submits to the server. Note the "url" parameter passed in the call as this will need to match your "/{controller}/{action}". Important: You will also need to update your "Search" button#API14 to type "button", not "submit", as this will avoid a postback which is undesired when making AJAX calls.
You can then add something like this to your controller:
public ActionResult SearchByProperty()
{
var model = new List<string>();
model.Add("one");
model.Add("two");
model.Add("three");
return PartialView(model);
}
... which will require the following in a partial view file I named SearchByProperty.cshtml:
#model List<string>
<table>
#foreach (var item in Model) {
<tr class="API14-item">
<td>#item</td>
</tr>
}
</table>
Step 2: "The user can then select which search result they want to use to which will then populate the original form. I think I can figure most of this out but wasnt sure of the best way to kick off the search from the modal. Code is as follows."
If you are confident in writing jQuery, then you should be able to write some js in the scripts section of your create page that will take the values you place in your table and populate your form:
$(document).on('click', '.API14-item', function () {
//
// TODO: your code here
//
});
Hope this helps!

Why is my <Form action=home/Update> is getting automatically changed upon loading the page?

I have a problem with a form on visual studio using ASP.NET.
This is my form:
<div class="form-horizontal">
<form method="post" action="/update">
<h4>Edit</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model[0].idContrato, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model[0].idContrato, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model[0].idContrato, "", new { #class = "text-danger" })
</div>
</div> ... <div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</form>
</div>
When I execute and inspect it, the line: <form method="post" action="/update"> is changed into <form action="/home/Edit/010001" method="post" novalidate="novalidate"> where /home/Edit/010001 is the URL of my page and 010001 the id of the contract I want to edit in my form.
So when I press the button validate, it refreshes the page and nothing happens.
Any idea?
Well, the answer was to delete the Using(Html.BeginForm()){}, but i'm still wondering why...

Viewmodel always null following file upload

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

mvc4 paging on partial view

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))
{
}
}

Categories

Resources