Asp.Net Mvc Form does not post? - asp.net-mvc

view
#model Osos12Mvc3.Models.TblSayaclar
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div id="div_dialog_container" class="dialog_container">
#using (Html.BeginForm((string)ViewBag.FormAction, "Sayac"))
{
<div id="div_iu_form_container" class="ui_form_container">
<div>#Html.ValidationSummary(true, "Sayaç Kaydı Başarısız! Lütfen Bilgileri Kontrol Ediniz.")
</div>
<table>
<thead>
<tr>
<th colspan="2">
Genel Bilgiler
</th>
</tr>
</thead>
<tbody>
<tr>
<td>#Html.LabelFor(x => x.TblMusteriler.musteri_adi):
</td>
<td>#Html.DropDownList("sno", (SelectList)ViewBag.musteri_id, "--Müşteri Seçiniz--")
</td>
</tr>
</tbody>
<tfoot>
</tfoot>
</table>
<table class="table_ui_buttons">
<thead>
<tr>
<th colspan="2">
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="submit" value="Kaydet" />
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
}
</div>
controller
public ActionResult SayacEkle()
{
var musteriler = entity.TblMusteriler.Select(x => new { x.sno, x.musteri_adi });
ViewBag.musteri_id = new SelectList(musteriler.AsEnumerable(), "sno", "musteri_adi");
return ContextDependentView(new TblSayaclar());
}
Im using validationsummary in my view. When I clicked submit dropdownlist color change to red. (like required field). I dont understand that state. I debugged post event, It did not posted. Post action was not firing.
This is the Html Source:
<select data-val="true" data-val-number="The field sno must be a number." data-val-required="The sno field is required." id="sno" name="sno" class="input-validation-error"><option value="">--Müşteri Seçiniz--</option>
AliRıza Adıyahşi
What is the wrong?
Thanks

When I clicked submit dropdownlist color change to red. (
If your view model property is marked with the Required attribute then it is normal that it gets validated:
[Required]
public string Sno { get; set; }
There are 2 levels of validation which run in that order:
Client side validation (not enabled by default, implement with jquery ubnobtrusive => prevent the form from being submitted)
Server side validation
If you are using client side validation (unobtrusive javascript) and you have a model error then the form will not even be posted to the server. The user needs to first fix his errors before being able to submit the form.

Related

Conditionally add markup based on model value

How can I test the value of a Model.IsCopy and render the Part Num textbox if false?
I tried using #Model.IsCopy but it's value is different than the value in #Html.HiddenFor(m=>m.IsCopy). Seems #Model is the empty class while m is the value passed into the Partial View.
#Html.HiddenFor(m => m.PartNum)
#Html.HiddenFor(m=> m.IsCopy)
<table>
<tr><td colspan="2" align="center"><h4 class="text-info"> Details</h4></td></tr>
<tr><td colspan="2" align="center"> <hr /></td></tr>
<tr>
<td width="30%">Part Num</td>
<td>
#{ if (#Model.IsCopy == false)
{
#Html.TextBoxFor(m => m.PartNum, new { ReadOnly = "true", Visibility = "true" })
}
}
</td>
</tr>
Inspecting in the browser shows the hidden field to be true but the Html.TextboxFor still renders.
<input name="IsCopy" id="IsCopy" type="hidden" value="true" data-val-required="The IsCopy field is required." data-val="true" data-bind="value:IsCopy">

MVC How to pass label data from view to controller?

I am trying to pass data from view to controller. I used BeginForm and i can pass data which users enter to textbox. But I want to also pass label data because label is filled automatically and i need to save this label text to database. How can i do?
View:
#using (Html.BeginForm("Room", "Booking", FormMethod.Post))
{
<table>
<tr>
<td align="left"><lable for="eventName">Description:</lable></td>
<td><input name="eventName" id="eventName"></td>
</tr>
<tr>
<td align="left"><lable for="startDate">Start Date : </td>
<td align="left"><label id="startDate" name="startDate" /></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td align="right" colspan="2">
<button type="submit" class="btn-primary" name="submit" id="submit">Save</button>
</td>
</tr>
<tr>
</tr>
</table>
}
Controller:
[HttpPost]
public ActionResult Room(FormCollection form)
{
using (BookingEntities ent = new BookingEntities ())
{
ReservationTBL Tbl = new ReservationTBL();
Tbl.Description = form["eventName"].ToString();
Tbl.startDate= form["startDate"].ToString();
ent.BookingTBL.Add(Tbl);
ent.SaveChanges();
}
return View();
}
The label data doesn't get send when you post your form. What you can do however is to add an input with type hidden that contains your label data.
Something like this:
<tr>
<td align="left"><label for="startDate">Start Date : </td>
<td align="left">
<label>#Model.StartDate</label>
<input type="hidden" name="startDate" value="#Model.StartDate" id="startDate"/>
</td>
</tr>

Trying to figure out Ajax.BeginForm

I have a view in 2 sections.
The top section I input fields and submit to save them.
In the second section I have an autocomplete textbox. I select an item in autocomplete, and when I click submit I want to add that item to a datatable.
So for the first part when I click submit I save the details via a HttpPost method on the controller.
For the second part I intend to save it via an Ajax call for the controller and then bring back a partial view with the results. I have not coded the partial view yet, that is next.
Now I am new to Ajax.BeginForm and I am struggling with it.
I was hoping that the submit button inside the Ajax.BeginForm would only apply to that part of the form.
But in fact it calls the HttpPost method for the whole form.
So how do I fix this?
My view looks like;
#using ITOF.HtmlHelpers
#model ITOF.Models.OngoingContractViewModel
#{
ViewBag.Title = "EditOngoingContractDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("EditOngoingContractDetails", "Contract", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contract.ContractId)
<h1>Edit Ongoing Contract Details</h1>
<fieldset>
<legend>#Model.Contract.Heading</legend>
<p>Where you see <span class="error">*</span> you must enter data.</p>
<table>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.EndDate)
</td>
<td>
#Html.EditorFor(model => model.Contract.EndDate)
</td>
</tr>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.Organogramme)
</td>
<td>
<input type="file" id="PDF" name="file" />
#Html.HiddenFor(model => model.Contract.Organogramme)
</td>
</tr>
#if (!string.IsNullOrWhiteSpace(Model.Contract.Organogramme))
{
<tr>
<td></td>
<td>
The current organogramme is <span class="HighlightTextRed">#Model.GetOrganogrammeName()</span>
for the contract <span class="HighlightTextRed">#Model.Contract.ContractName</span><br/>
Click here to see the last saved organogramme
</td>
</tr>
}
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.AssistantRLOManagerId)
</td>
<td>
#Html.DropDownListFor(model => model.Contract.AssistantRLOManagerId, Model.AssistantRloManagerSelectList, "--N/A--")
</td>
</tr>
#if (this.TempData["SuccessMessage"] != null)
{
<tr>
<td colspan="2" class="success">#this.TempData["SuccessMessage"].ToString()</td>
</tr>
}
<tr>
<td colspan="2" style="padding-top: 20px; text-align: center;"><input type="submit" value="Save" /></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>Add an existing Site to this contract: </legend>
#using (Ajax.BeginForm("AddExistingSite", new AjaxOptions { UpdateTargetId = "siteRows" }))
{
<input type="text" name="q" style="width: 800px"
data-autocomplete="#Url.Action("SiteSearch", "DataService", new { contractId = #Model.Contract.ContractId })" />
<input type="submit" value="Add site to contract" />
}
#if (Model.SiteList.Count > 0)
{
<table id="siteDataTable" class="display">
<thead>
<tr>
<th>Main Site?</th>
<th>Type</th>
<th>Address</th>
<th>Map</th>
<th>Telephone</th>
<th>Email</th>
</tr>
</thead>
<tbody id="siteRows">
#foreach (var item in Model.SiteList)
{
<tr id="#item.SiteContract.SiteContractId">
<td>#item.SiteContract.MainSiteFlag</td>
<td>#item.Site.SiteType</td>
<td>#item.Site.Address</td>
<td>#item.Site.MapUrl</td>
<td>#item.Site.Telephone</td>
<td>#item.Site.Email</td>
</tr>
}
</tbody>
</table>
<div class="add_delete_toolbar" />
}
#Html.ListLink("Back to List")
</fieldset>
}
Oh no, you just cannot nest HTML forms. That's not supported. You will have to rethink your design. This really has absolutely nothing to do with ASP.NET MVC and things like Html.BeginForm or Ajax.BeginForm. The HTML specification simply tells you that the <form> tag cannot be nested and if you nest it you will get undefined behavior that could vary between browsers.
For example you could implement the autocomplete functionality using jquery UI autocomplete plugin and get rid of the Ajax.BeginForm.

MVC list of checkboxes check and select to Action then to csv file

I have a view like:
#model IEnumerable<VectorCheck.Models.Invoice>
#{
ViewBag.Title = "Exportable Invoices";
}
<script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.16.min.js" type="text/javascript"></script>
<script src="../../Scripts/Views/Export/index.js" type="text/javascript"></script
<header class="header">
<div class="headerText">
<h1>Exportable Invoices</h1>
</div>
</header>
#using (Html.BeginForm("Export", "Export")) {
<table>
<tr class="mainheader">
<th>Invoice Number</th>
<th>Date</th>
<th>Organisation</th>
<th>Total (Excl GST)</th>
<th>Status</th>
<th>Exported Date</th>
<th>
<select id="expenseSelect"></select>
<input type="submit" id="btnexport" value="Export" />
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.InvoiceNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceDate, "{0:D}")
</td>
<td>
#Html.DisplayFor(modelItem => item.Organisation.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.TotalExcludingGst)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.ExportedDateTime)
</td>
<td class="centered">
<input type="checkbox" class="exportcheckbox" data-invoiceid=#item.InvoiceId />
</td>
</tr>
}
</table>
}
<div>
#Html.ActionLink("Back to Summary", "Index", "Invoice")
</div>
Ok, so see how each checkbox has an attribrute data-invoiceid=#item.InvoiceId. Well I'm trying to get to an action method the Ids of all the invoices that have had their checkboxes checked. Also I'm trying to get the id of the selectlist expenseSelect which has options added to it on page load via jquery. I managed to achieve this with jquery and then sending the data with a $.post. The problem is in the file I'm sending the info to:
public ActionResult Export()
{
...
var csvData = _utility.GetCsvData(data);
return File(Encoding.UTF8.GetBytes(csvData), "text.csv", "invoices.csv");
}
brings up a save/open file dialog. I'm been informed this won't work for the jquery ajax call and I need to post the info back using a submit.
That's fine but now I have no idea how to send the select id and a list of the ids of the checked checkboxes to the method. Can anybody show me how to go about this?
You don't need any HTML5 data-* attributes since they are not sent to the server when you submit the form. In order to send their values you will have to use AJAX but this won't work with file downloads. So simply give your checkboxes a name:
<td class="centered">
<input type="checkbox" class="exportcheckbox" name="ids" value="#item.InvoiceId" />
</td>
and then on the server the default model binder will automatically construct an array of the ids of the checked items:
[HttpPost]
public ActionResult Export(int[] ids)
{
byte[] data = ...
return File(data, "text/csv", "invoices.csv");
}
Depending on the type of InvoiceId you might need to adjust the type of the action argument.
Radically changing my answer...
You could dynamically add a hidden IFRAME to your page. The IFRAME src can take your selected "ids" as a querystring parameter. This should get your your download dialog.
Got some help with the jquery from here: JQuery: Turn array input values into a string optimization
var selectedIdsArray = $(":checked").map(function(){return $(this).attr('data-invoiceid');});
var url = '#Url.Action("Export", "Export")?csv=' selectedIdsArray.get().join(',');
$('body').append("<iframe style='visibility:hidden' src='"+url +"'/>");

MVC Model with multiple HttpPostedFileBase properties

I'm using the following model with my get/post actions.
Public Class AuthorEditQuestionViewModel
<Required()>
<Display(Name:="Question Title")>
Public Property Title As String
<Display(Name:="Start Ledger")>
Public Property StartLedger As HttpPostedFileBase
Public Property StartLedgerUrl As String
<Display(Name:="End Ledger")>
Public Property EndLedger As HttpPostedFileBase
Public Property EndLedgerUrl As String
<Required()>
<Display(Name:="Introduction/Instructions")>
Public Property IntroductionHtml As String
End Class
The html for the ledger fields is as follows.
<input type="file" id="StartLedger" name="StartLedger" />
<input type="file" id="EndLedger" name="EndLedger" />
However, in the post action, it seems that both the StartLedger and EndLedger properties seem to be populated with the same value (the first file).
Does anyone have any examples of handling multiple named file upload fields with MVC3? It really feels like supporting file uploads well has been a shortcoming in ASP.Net MVC since version 1.
---- EDIT (.vbhtml below)
#Using Html.BeginForm("EditQuestion", "Author", Nothing, FormMethod.Post, New With {.enctype = "multipart/form-data"})
#Html.ValidationSummary("Please correct the following issues.")
#<table class="form">
<tr>
<td class="label">#Html.LabelFor(Function(m) m.Title)</td>
<td class="input">
#Html.TextBoxFor(Function(m) m.Title)
</td>
</tr>
<tr>
<td class="label">#Html.LabelFor(Function(m) m.StartLedger)</td>
<td class="input">
<input type="file" id="StartLedger" name="StartLedger" />
#If Not String.IsNullOrWhiteSpace(Model.StartLedgerUrl) Then
#Download
End If
</td>
</tr>
<tr>
<td class="label">#Html.LabelFor(Function(m) m.EndLedger)</td>
<td class="input">
<input type="file" id="EndLedger" name="EndLedger" />
#If Not String.IsNullOrWhiteSpace(Model.EndLedgerUrl) Then
#Download
End If
</td>
</tr>
<tr>
<td class="label" colspan="2">#Html.LabelFor(Function(m) m.IntroductionHtml)</td>
</tr>
<tr>
<td class="input" colspan="2">#Html.TextAreaFor(Function(m) m.IntroductionHtml, 10, 80, Nothing)</td>
</tr>
<tr>
<td class="buttons" colspan="2">
<button class="action" data-action="#Url.Action("Index")">Cancel</button>
<button>Save</button>
</td>
</tr>
</table>
End Using
The signature for the action is as follows...
Function EditQuestion(id As Guid?, model As AuthorEditQuestionViewModel) As ActionResult

Resources