Showing a toast notification on form submission - javascript

I am new to ASP.NET MVC 5. I am having trouble displaying a toast notification when I submit a form in MVC 5. It does not display on the page after I click submit. This is the code:
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(ContactData formdata)
{
//what is supposed to happen when form is successful and there are no validation errors
if (ModelState.IsValid)
{
var data = new ContactData
{
FirstName = formdata.FirstName,
LastName = formdata.LastName,
Email = formdata.Email,
Message = formdata.Message
};
//add the message to the messages table and then save the changes
_dbContext.Messages.Add(data);
_dbContext.SaveChanges();
TempData["Success"] = "Success";
return RedirectToAction("Contact","Home");
}
return View(formdata); //else re display the form showing the validation errors
}
This is the JavaScript in the View:
#section Scripts{
<script>
$(document).ready(function () {
if (TempData.ContainsKey("Success")) {
toastr.success("Message Sent Successfully");
}
}
</script>
}
Note: I have implemented the form using HTML helper methods rather than JQuery. This is my form:
#using (Html.BeginForm("Contact", "Home", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<br /><br />
#Html.AntiForgeryToken()
#Html.ValidationSummary() <!--shows a list of the validation errors-->
<div class="row col-sm-12 col-md-12 col-lg-12">
<div class="col-sm-4 col-md-4 col-lg-4">
<strong>Leave a Message:</strong>
</div>
<span class="clearfix"></span> <!--makes the content go to the left-->
<div class="form-group col-sm-4 col-md-4 col-lg-4" style="margin-left:4px;">
#Html.LabelFor(t => t.FirstName)
#Html.TextBoxFor(t => t.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(t => t.FirstName, String.Empty, new { #style = "color:red;!important" })
</div>
<span class="clearfix"></span>
<div class="form-group col-sm-4 col-md-4 col-lg-4" style="margin-left:4px;">
#Html.LabelFor(t => t.LastName)
#Html.TextBoxFor(t => t.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(t => t.LastName, String.Empty, new { #style = "color:red;!important" })
</div>
<span class="clearfix"></span>
<div class="form-group col-sm-4 col-md-4 col-lg-4" style="margin-left:10px;">
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email, String.Empty, new { #style = "color:red;!important" })
</div>
<span class="clearfix"></span>
<div class="form-group col-sm-4 col-md-4 col-lg-4" style="margin-left:10px;">
#Html.LabelFor(m => m.Message)
#Html.TextAreaFor(m => m.Message, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Message, String.Empty, new { #style = "color:red;!important" })
</div>
<span class="clearfix"></span>
<div class="form-group col-sm-4 col-md-4 col-lg-4" style="margin-left:10px;">
<input id="btnRegister" type="submit" class="btn btn-success" value="Submit" />
</div>
</div>
}
I don't know what I am doing wrong. Thank you.

I believe the problem is that TempData is in your Controller, and would need to be handled in your View as a part of the Model, or, if you have access to to TempData in your view, you'd need to define it in a Razor block like this:
<script>
var jsTempDataSuccess = '#TempData["Success"]';
</script>
And then in your document ready, you can do this:
<script>
$(document).ready(function () {
if (jsTempDataSuccess && jsTempDataSuccess == "Success") {
toastr.success("Message Sent Successfully");
}
}
</script>

The expression TempData is server side code, So you should prefix it with #.
I like to render the script inside an if condition so that if TempData.ContainsKey("Success") returns false, the script will not be even rendered to the page (less script to compile and parse)
$(document).ready(function ()
{
#if(TempData.ContainsKey("Success"))
{
#:toastr.success("Message Sent Successfully");
}
});

Related

How to open a dialog box after submit a form to show posted successfully - asp.net MVC

I'm working on a asp.net MVC project. I want to show user a dialog box after form posted, for user to understand if it was successful or not, and also if user wants to close the dialog box it would be possible.
I searched a lot and read something that I can return partial view but i'm not sure if partial view is what I need in this situation
my question is that is it possible to do it a way with java-script with .dialog() or if I should use partial view, then please give me a little explanation how it works.
I need something like this to show after user click on submit button
http://jsfiddle.net/db5SX/
here is my controller:
public ActionResult Index()
{
ViewBag.ResultMessage = TempData["ResultMessage"];
return View();
}
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Email,Phone,Message,Date")] Contact_US contact_US)
{
if (ModelState.IsValid)
{
db.Contact_US.Add(contact_US);
db.SaveChanges();
TempData["ResultMessage"] = "POSTED SUCESSFULLY...! We WILL CONTACT YOU SOON.";
return RedirectToAction("Index");
}
return View(contact_US);
}
here is my view if needed:
<div class="form-group col-md-8">
<h3 class="txtformat padbot50px">Get in touch with us</h3>
<div class="text-danger message ">
#ViewBag.ResultMessage
</div>
#using (Html.BeginForm("Create", "Contact_Us", FormMethod.Post, new { #id = "contactusform" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2 txtformat" })
<div class="col-md-12">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2 txtformat" })
<div class="col-md-12">
#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.Phone, htmlAttributes: new { #class = "control-label col-md-2 txtformat" })
<div class="col-md-12">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group hidden">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Message, htmlAttributes: new { #class = "control-label col-md-2 txtformat" })
<div class="col-md-12 contactusmsg">
#Html.TextAreaFor(model => model.Message, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Message, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group contactuspostbtn">
<div class="col-md-12">
<input id="postcontactusmessage" type="submit" value="Send" class="btn btn-default" data-toggle="modal" data-target="#myModal" />
</div>
</div>
</div>
}
</div>
</div>
information of my layout if needed :
<script src="~/Scripts/jquery-3.1.0.min.js"></script>
<link href="~/Scripts/jquery-ui-1.12.1.custom/jquery-ui.css" rel="stylesheet" />
<script src="~/Scripts/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<script src="~/Scripts/tinymce/tinymce.min.js"></script>
A good way to do this is to have it abstracted in a base controller and show the message in the _layouts.cshtml file, for example:
Create a base controller that will be inherited by all of your controllers
public class BaseController : Controller
{
public string SucccessMessage
{
get
{
return TempData["SuccessMessage"] as string;
}
set
{
TempData["SuccessMessage"] = value;
}
}
public string ErrorMessage
{
get
{
return TempData["ErrorMessage"] as string;
}
set
{
TempData["ErrorMessage"] = value;
}
}
}
In _Layouts.cshtml,
<div class="container body-content" id="bodyContainer">
<div class="spacer"></div>
#if (#TempData["SuccessMessage"] != null)
{
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
#TempData["SuccessMessage"]
</div>
}
else if (#TempData["ErrorMessage"] != null)
{
<div class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
#TempData["ErrorMessage"]
</div>
}
<div class="spacer"></div>
#RenderBody()
<hr id="hr" />
<footer>
<p>© #DateTime.Now.Year - Your APp </p>
</footer>
</div>
Now, all you need to do inside your controller is:
public class MyController:BaseController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Email,Phone,Message,Date")] Contact_US contact_US)
{
if (ModelState.IsValid)
{
db.Contact_US.Add(contact_US);
db.SaveChanges();
SucccessMessage = "POSTED SUCESSFULLY...! We WILL CONTACT YOU SOON.";
return RedirectToAction("Index");
}
return View(contact_US);
}
}

Upload image to database

Im trying to figure out how I can upload a profile image to my database within my asp.net mvc web project.
The issues is that im getting a Data URI instead of an actual file upload and that the URI is generated inside my javascript and im not sure how I can pass URI aswell as the other input fields inside my form to the controller.
View - Form
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.ProfilePicture, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
<div id="wrapper" style="margin-top: 20px;">
<div class="image-editor">
<input type="file" class="cropit-image-input">
<div class="cropit-preview"></div>
<div class="image-size-label">
Resize image
</div>
<div class="controls-wrapper">
<div class="slider-wrapper">
<span class="icon icon-image small-image"></span>
<input type="range" class="cropit-image-zoom-input custom">
<span class="icon icon-image large-image"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="hidden" name="profilePicture" class="hidden-image-data">
<input type="submit" class="btn btn-default" value="Register"/>
</div>
</div>
}
Javascript below the Form
<script src="~/Scripts/jquery.cropit.js"></script>
<script>
$(function() {
$('.image-editor').cropit({
imageBackground: true,
imageBackgroundBorderWidth: 20,
initialZoom: 'image',
smallImage: 'stretch',
imageState: {
src: '/Images/ProfilePictures/no-img.png'
}
});
$('form').submit(function () {
var imageData = $('.image-editor').cropit('export');
// imageData containing the Data URI for the cropped image
$('.hidden-image-data').val(imageData);
});
});
</script>
Controller - Register
public async Task<ActionResult> Register([Bind(Exclude = "ProfilePicture")]RegisterViewModel model) {
if (ModelState.IsValid) {
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0) {
HttpPostedFileBase poImgFile = Request.Files["ProfilePicture"];
using (var binary = new BinaryReader(poImgFile.InputStream)) {
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
.... more code ....
}
}
Feel free to ask for more explanatory details.
A data URI is a non-binary encoding of binary data. That is the data you want.
It's probably base64 encoded so you can just base64 decode it on the server side before you write it.
There's code here to encode into and from base64
Here's the example code from the site linked above:
public class Base64Decoder
{
public static void Main ()
{
string inputText = "This is some text.";
Console.Out.WriteLine ("Input text: {0}", inputText);
byte [] bytesToEncode = Encoding.UTF8.GetBytes (inputText);
string encodedText = Convert.ToBase64String (bytesToEncode);
Console.Out.WriteLine ("Encoded text: {0}", encodedText);
byte [] decodedBytes = Convert.FromBase64String (encodedText);
string decodedText = Encoding.UTF8.GetString (decodedBytes);
Console.Out.WriteLine ("Decoded text: {0}", decodedText);
Console.Out.Write ("Press enter to finish.");
Console.In.ReadLine ();
return;
}
}

How to disable/hide a Partial View based on IList values?

I want to disable or hide a PartialView based on values inside two different ILists. Both of these lists are stored in two Session variables, _UserRoleList and _PartialRoleList.
The list contents of _UserRoleList are of type User which contains the following properties:
UserName
RoleID
RoleDescription
SID
The list contents of _PartialRoleList are of type PartialRole which contains the following properties:
PartialName
RoleID
AccessLevelID
AccessLevelDescription
Case 1 - Disable all input controls inside the Partial View:
Disable ALL input controls (textboxes, listboxes, checkboxes, dropdownlists) on the specified PartialView (with an id of "frmClientDetails") if a RoleID of 3 is found in both session lists.
Case 2 - Set all input controls to read-only inside the Partial View:
All input controls (textboxes, listboxes, checkboxes, dropdownlists) on the specified PartialView (with an id of "frmClientDetails") should have their read-only attribute set to true if aRoleID of 2 is found in both session lists.
Question:
Would it be better to retrieve the two lists and then use a jQuery .each to loop through and search for equality on the RoleID fields? Would another option be to use Razor? If pseudo code could be provided, that would be a great help.
Controller snippet:
public ViewResult Index() /* Master View, starting point of application */
{
int userID;
IList<User> userRoleList;
IList<PartialRole> partialRoleList;
WindowsIdentity identity = null;
identity = WindowsIdentity.GetCurrent();
userRoleList = _homeService.GetUserDetails(identity.User.ToString());
userID = userRoleList.First().ID;
partialRoleList = _homeService.GetPartialDetails(userID);
if (Session["_UserRoleList"] == null)
{
HttpContext.Session.Contents.Add("_UserRoleList", userRoleList);
}
if (Session["_PartialRoleList"] == null)
{
HttpContext.Session.Contents.Add("_PartialRoleList", partialRoleList);
}
return View();
}
Original View - ClientDetails.cshtml:
#using InvoiceManagement.Models
#model InvoiceClient
#{
InvoiceCreditNoteViewModel viewModel = new InvoiceCreditNoteViewModel();
viewModel.Client = Model;
ViewBag.Title = "Client Details";
List<User> userRoleList = Session["_UserRoleList"] != null ? (List<User>)Session["_UserRoleList"] : null;
List<PartialRole> partialRoleList = Session["_PartialRoleList"] != null ? (List<PartialRole>)Session["_PartialRoleList"] : null;
}
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
$('input[type=radio][name=optionInvoiceCreditNote]').change(function () {
if (this.value == 'invoice') {
$("#InvoiceGrid").show();
$("#CreditNoteGrid").hide();
}
else if (this.value == 'creditNote') {
$("#InvoiceGrid").hide();
$("#CreditNoteGrid").show();
}
});
$('#showActive').click(function (e) {
if($(this).prop('checked') === true){
var url = '#Url.Action("FilterActiveOnlyAgreements")';
$.get(url, { invoiceClientID: '#Model.ID' }, function (result) {
$('#agreementGrid').html(result);
});
}
else {
var url = '#Url.Action("FilterAllAgreements")';
$.get(url, { invoiceClientID: '#Model.ID' }, function (result) {
$('#agreementGrid').html(result);
});
}
});
});
</script>
}
#Html.Partial("ClientDetailsFormPartial", viewModel.Client)
#if (viewModel.Client.ID > 0)
{
#Html.Partial("ClientDetailsAgreementPartial")
#Html.Partial("InvoiceCreditNoteContainerPartial", viewModel)
}
Partial View - ClientDetailsFormPartial:
#using InvoiceManagement.Models
#model InvoiceClient
#using (#Html.BeginForm("ClientDetails", "Client", FormMethod.Post, new { #id = "frmClientDetails" }))
{
<div class="container-fluid">
<div class="row">
<div class="col-xs-2">
<h2>Client Details</h2>
</div>
<div class="col-xs-2" style="min-height: 70px;">
Search New Client
</div>
<div class="form-group col-xs-2" style="min-height: 70px;">
<div class="input-group" style="top: 21px">
<span class="input-group-addon" id="client-ID">Client ID</span>
#Html.TextBox("ID", Model.ID, new { #class = "form-control", #readonly = "readonly" })
</div>
<div class="has-error">
#Html.ValidationMessageFor(m => m.ID, String.Empty, new { #class = "help-block" })
</div>
</div>
<div class="form-group col-xs-3" style="min-height: 70px;">
<div class="input-group" style="top: 21px">
<span class="input-group-addon" id="accounting-ID">Accounting ID</span>
#if (Model.AID == null && Model.ID == 0)
{
#Html.TextBoxFor(m => m.AID, new { #class = "form-control" }) }
else
{
#Html.TextBoxFor(m => m.AID, new { #class = "form-control", #readonly = "readonly" }) }
</div>
</div>
<div style="padding-top: 22px;">
<div class="has-error">
#Html.ValidationMessageFor(m => m.AID, String.Empty, new { #class = "help-block" })
</div>
</div>
</div>
<div class="row">
<div class="form-group col-xs-7">
<div class="input-group">
<span class="input-group-addon" id="client-name">Client Name</span>
#Html.TextBoxFor(m => m.InvoiceClientName, new { #class = "form-control", #name = "InvoiceClientName" })
</div>
<div class="has-error">
#Html.ValidationMessageFor(m => m.InvoiceClientName, String.Empty, new { #class = "help-block" })
</div>
</div>
</div>
<div class="row">
<div class="form-group col-xs-3">
<div class="input-group">
<span class="input-group-addon" id="default-tax-code-1">Default Tax Code 1</span>
#Html.DropDownListFor(m => m.DefaultTaxCodeID1, (IEnumerable<SelectListItem>)ViewBag.PopulateDefaultTaxCode1, new { #class = "form-control", #id = "default-tax-code1-ID", #name = "defaultTaxCodeID1" })
</div>
</div>
<div class="form-group col-xs-3 col-xs-offset-1">
<div class="input-group">
<span class="input-group-addon" id="default-tax-code-2">Default Tax Code 2</span>
#Html.DropDownListFor(m => m.DefaultTaxCodeID2, (IEnumerable<SelectListItem>)ViewBag.PopulateDefaultTaxCode2, new { #class = "form-control", #id = "default-tax-code2-ID", #name = "defaultTaxCodeID2" })
</div>
</div>
</div>
<div class="row">
<div class="form-group col-xs-3">
<div class="input-group">
<span class="input-group-addon" id="status">Status</span>
#Html.DropDownListFor(m => m.StatusID, (IEnumerable<SelectListItem>)ViewBag.PopulateStatus, new { #class = "form-control", #id = "status-ID", #name = "statusID" })
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-7">
#if (Model == null || Model.ID == 0)
{
<button type="submit" class="btn btn-default">Add New Client</button>
}
else
{
<button type="submit" class="btn btn-default">Update Existing Client</button>
}
</div>
</div>
</div>
}
Since disabled controls will not post back, its pointless to generate all that extra html, and since readonly controls cannot be edited, again it seems pointless to generate all that extra html and then send it all back unchanged to the server when you submit your form.
A better approach, performance wise would be to have 2 partial views (say) _ClientDetails.cshtml and _ReadOnlyClientDetails.cshtml. The first would contain your form and its editable controls and submit button, and the second would contain only the text values of your properties, for example
#Html.DisplayNameFor(m => m.InvoiceClientName)
#Html.DisplayFor(m => m.InvoiceClientName)
Then in your controller method that generates you main view, set a view model property (or ViewBag property) to indicate which partial to display, for example
ViewBag.IsReadonly = true; // or omit depending on your logic
and in the main view
#if(ViewBag.IsReadonly)
{
#Html.Partial("_ReadOnlyClientDetails", viewModel.Client)
}
else
{
#Html.Partial("_ClientDetails", viewModel.Client)
}
Side note: Everything between you first #{ ... } except ViewBag.Title = "Client Details"; belongs in the controller method, not the view. And to do something like viewModel.Client = Model; makes no sense at all. Your view should be #model InvoiceCreditNoteViewModel and since you're not passing a model to the view, then viewModel.Client = Model; would not make sense anyway since its always null.
Its also not clear why your using Session. The code in your controller should be something like
IList<User> userRoleList = _homeService.GetUserDetails(identity.User.ToString());
int userID = userRoleList.First().ID;
IList<PartialRole> partialRoleList = _homeService.GetPartialDetails(userID)
List<int> values = new List<int>(){ 2, 3 };
if (userRoleList.Any(x => values.Contains(x.RoleID)) && partialRoleList.Any(x => values.Contains(x.RoleID)))
{
ViewBag.IsReadonly = true;
}

how to send a form that contains another form

I have a form that contains another form.
the first form sends data to the action indicated in the beginform which the particular form it contains.
The second form ( contained in the first ) is a list that on change event, exchange a picture, this works .
but the first form is not sent yet.
how can I do to submit the first form normaly and the second with the javascript on change ?
#using (Html.BeginForm("VCreateCommande", "CCommande", new {id="formretouche"}, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
var imagedefaut = "";
#Html.AntiForgeryToken()
<h4>Retouchephoto</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group ilnblk">
<div class="control-label col-md-2 fltleft">Type de retouche</div>
<div class="col-md-10 fltleft">
#using (Html.BeginForm("VCreateCommande", "CCommande", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.DropDownListFor(model => model.Ttyperetouche.Idtyperetouche, new SelectList(
Model.Ttyperetouches, "Idtyperetouche", "libelle", ViewData["Idtyperetouche"]), new { #onchange = "this.form.submit()" })
} </div>
<div class="fltleft imagemodele">
#if (ViewData["Idtyperetouche"] != null)
{
foreach (var typeretouche in Model.Ttyperetouches)
{
if (typeretouche.Idtyperetouche.ToString() == ViewData["Idtyperetouche"].ToString())
{
imagedefaut = typeretouche.SRCtyperetouche;
}
}
}
else
{
imagedefaut = Model.Ttyperetouches.First().SRCtyperetouche;
}
<img src="#imagedefaut" />
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">Support papier</div>
<div class="col-md-10">
#Html.CheckBoxFor(model => model.Tretouche.Supportpapier, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Tretouche.Supportpapier, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">Quantité</div>
<div class="col-md-10">
#Html.EditorFor(model => model.Tretouche.Quantite, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Tretouche.Quantite, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">Photo...</div>
<div class="col-md-10">
#Html.TextBoxFor(model => model.Tretouche.fichierphoto, new { type = "file" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
#{
String onclick = String.Format("Submit(this)",
Html.Encode(ViewBag.returnUrl));
}
<input type="button" id="btnsubmitretouche" value="Ajouter1" onclick="#onclick" />
<input type="submit" value="Ajouter" class="btn btn-default"/>
</div>
</div>
}
It is not valid html5 to nest forms, see the W3C HTML5 Working Draft.

How do I get Bootstrap file input data to controller in MVC 5

I'm using the Bootstrap File Input plugin to upload an image in my ASP.Net MVC 5 application form. I'm not sure what I need to see on the controller or what I need to do in javascript to get this to work. Currently there is an error that is being thrown when I submit my data in the form that says
"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
Here is my StudentController.
[HttpPost]
public ActionResult Edit(EditStudentViewModel studentViewModel)
{
if (ModelState.IsValid)
{
...other code left out
Here is my javascript
$("#input-20").fileinput({
'type': 'POST',
'cache': false,
'browseClass': 'btn btn-primary btn-block',
'showCaption': false,
'showRemove': false,
'showUpload': false,
'uploadAsync': false,
'maxFileCount': 1,
'allowedFileExtensions': ['jpg', 'png', 'gif'],
'allowedFileTypes': ['image']
'uploadUrl': '#Url.Action("Edit", "Student")'
});
*Are these the correct 'uploadUrl' parameters
Here is my form that submits the data to the controller. You can see I'm submitting what in the ViewModel as well as the image. The byte[] that represents the iamge is in the view model
#model YogaBandy.DomainClasses.ViewModels.Student.EditStudentViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.Partial("_MenuPartial")
<div class="row submenurow">
#Html.Partial("_StudentTeacherProfilePartial")
<div class="col-md-9 submenucol2">
#using (Html.BeginForm("Edit", "Student", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.StudentId)
#Html.HiddenFor(model => model.AspNetUserRefId)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Student Picture</h3>
</div>
<div class="panel-body">
#Html.TextBoxFor(model => model.TestImage, new { #type = "file", #id = "input-20" })
</div>
</div>
<br/>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Student Profile</h3>
</div>
<div class="panel-body">
<div class="form-group">
#Html.LabelFor(model => model.CatchPhrase, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-sm-10">
#Html.EditorFor(model => model.CatchPhrase, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CatchPhrase, "", new { #class = "text-danger" })
</div>
</div>
...other form-group's left out below to save space
</div>
</div>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
</div>
Here is my ViewModel being submitted to the controller
public class EditStudentViewModel
{
public byte[] TestImage { get; set; }
...other values left out
}

Categories