Ajax form submission with Valums plugins in asp.net mvc 3 - asp.net-mvc-3

I have used Valums uploader plugins for file uploads in asp.net mvc 3. Following is the views which have form fields and ajax query upload button inside form. I am not sure that I am doing it right or not. What I have to change on view so that When I Choose the file to upload the form field's value is also send.
Views:
<link href="#Url.Content("~/Content/css/fileuploader.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Content/js/fileuploader.js")" type="text/javascript"></script>
#using (Html.BeginForm("Upload","AjaxUpload")) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Upload Image File</legend>
<div class="editor-label">
#Html.Label("Select Language")
</div>
<div>
#Html.DropDownList("Language1", (SelectList) ViewBag.lang)
</div>
<div class="editor-label">
#Html.Label("Select Category")
</div>
<div>
#Html.DropDownList("ParentCategoryID", ViewBag.ParentCategoryID as SelectList)
</div>
<div id="file-uploader">
<noscript>
<p>
Please enable JavaScript to use file uploader.</p>
</noscript>
</div>
</fieldset>
}
**<script type="text/javascript">
var uploader = new qq.FileUploader
({
element: document.getElementById('file-uploader'),
action: '#Url.Action("upload")', // put here a path to your page to handle uploading
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'], // user this if you want to upload only pictures
sizeLimit: 4000000, // max size, about 4MB
minSizeLimit: 0 // min size
});
</script>**
How Can I passed the value of form to controller of HTTPOST Action So that I can save data to the database. Here, I have Upload action which save the data in database but I don't know to retrieve to those value send by form post.
HttpPost Action
[HttpPost]
public ActionResult Upload(HttpPostedFileBase qqfile)
{
var wav = new PlayWav
{
Name = ***filename***,
CategoryID = ***value from category dropdown select list***,
UserID = repository.GetUserID(HttpContext.User.Identity.Name),
LanguageID = int.Parse(***value from language dropdown select list***),
UploadDateTime = DateTime.Now,
ActiveDateTime = DateTime.Now,
FilePath = "n/a"
};
if (qqfile != null)
{
// this works for IE
var filename = Path.Combine(Server.MapPath("~/App_Data/Uploads"), Path.GetFileName(qqfile.FileName));
qqfile.SaveAs(filename);
return Json(new { success = true }, "text/html");
}
else
{
// this works for Firefox, Chrome
var filename = Request["qqfile"];
if (!string.IsNullOrEmpty(filename))
{
filename = Path.Combine(Server.MapPath("~/App_Data/Uploads"), Path.GetFileName(filename));
using (var output = System.IO.File.Create(filename))
{
Request.InputStream.CopyTo(output);
}
**db.PlayWavs.Attach(wav);
db.SaveChanges();**
return Json(new { success = true });
}
}
return Json(new { success = false });
}

Didn't you read the documentation? There's a whole section entitled Sending additional params. Even an example is given:
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '/server-side.upload',
// additional data to send, name-value pairs
params: {
param1: 'value1',
param2: 'value2'
}
});

Related

Uploading gallery images using filesystem in Entity Framework

I want to upload gallery images to ASP.NET MVC 5 application using filesystem upload. I added
public IEnumerable<string> GalleryImages { get; set; }
to my ProductModel, built solution and performed update-database in the package manager console. But, the property is not added to the Product table and when I try to add and then edit a product, I get this error:
System.ArgumentNullException: 'Value cannot be null.
Parameter name: source'
Also, I added this piece of code to Edit.cshtl:
#if (!Model.GalleryImages.Any())
{
<h4>There are no gallery images for this product.</h4>
}
<form action="/AdminPanel/Product/SaveGalleryImages" method="post" enctype="multipart/form-data" class="dropzone" id="dropzoneForm">
<div class="fallback">
<input type="file" name="file" multiple />
<input type="submit" value="Upload" />
</div>
</form>
<br /><br />
#foreach (var image in Model.GalleryImages)
{
<div style="display: inline-block">
<img src="/Images/Uploads/Products/#Model.Id/Gallery/Thumbs/#image" />
#Html.ActionLink("delete", "DeleteImage", "Product", new { #class = "deleteimage", data_name = image })
</div>
}
<link href="~/Scripts/dropzone/basic.css" rel="stylesheet" />
<link href="~/Scripts/dropzone/dropzone.css" rel="stylesheet" />
#section Scripts{
<script src="~/Scripts/dropzone/dropzone.js"></script>
<script>
$(function () {
//preview image
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$("img#imgpreview").attr("src", e.target.result).width(200).height(200);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#ImageUpload").change(function () {
readURL(this);
});
//dropzone js
Dropzone.options.dropzoneForm = {
acceptedFiles: "image/*",
init: function () {
this.on("complete", function (file) {
if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
location.reload();
}
});
this.on("sending", function (file, xhr, formData) {
formData.append("id", #Model.Id);
});
}
};
//dropzone js
$("a.deleteimage").click(function (e) {
e.preventDefault();
if (!confirm("confirm deletion"))
return false;
var $this = $(this);
var url = "/admin/shop/DeleteImage";
var imageName = $this.data("name");
$.post(url, { id: #Model.Id, imageName: imageName }, function (data) {
$this.parent().fadeOut("fast");
});
});
});
</script>
}
UPDATE:
What exactly do you expect as a column datatype when you model it as List<string>? SQL Server doesn't have any column data type to handle an arbitrary list of strings....
If you have an 1:n relationship between ProductModel and gallery images, you should really have a separate model class that holds the image information - e.g. MyImages. Then you could add a collection-style property
public virtual ICollection<MyImages> GalleryImages
to your ProductModel class.
SQL Server can't really handle List<string> as a column type .....
The steps needed to get this done are:
Change your C# model class (you've done this already)
Run add-migration migration-name so that an EF migration is added to your project (you seem to have skipped this step)
Run update-database to actually apply that migration to the database.
Only if you've completed ALL 3 steps in exactly this order are changes from your C# model class actually applied to the database - you CANNOT simply skip step #2 ....

Returning ValidationSummary in Partial View to Ajax error handler - nothing else getting rendered

I'm calling a method from Ajax that updates a some content in the page by loading up a partial view & setting a contained property appropriately.
This all works ok but I'm having problems with server side validation using the ValidationSummary control. I'm using an approach suggested elsewhere to stick the ValidationSummary in a partial view. (I've actually got client side validation turned off & I'm trying to get server side validation to work using the same validation summary that client side validation uses)
When there is a validation error, ajax error handler should update the contents of a div with the partial view that is returned.
All this works ok in the sense that the validation summary is rendered with the expected error messages except for the fact that the nothing else is getting displayed on the page other than the partial view containing the validation summary and its containing elements. i.e. no siblings / of the div are getting rendered
I reaslly haven't got a clue what's going on. Intersetingly, if I comment out the line in the error handler that updates the div with the partial, I see the form in its entirety again.
I'm using an ExceptionFilter:
public class ValidationErrorAttribute : FilterAttribute, IExceptionFilter
{
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.Exception != null)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode =
(int)System.Net.HttpStatusCode.BadRequest;
//return the partial view containing the validationsummary and set the ViewData
//so that it displays the validation error messages
filterContext.Result = new PartialViewResult { ViewName = "validation",
ViewData = filterContext.Controller.ViewData };
}
}
}
when there's a validation error, throw a validationexception which will
trigger the OnException method of the filter
//Controller
[HttpPost]
[ValidationErrorAttribute]
public ActionResult Save(ConsumptionData consumptionData)
{
if (ModelState.IsValid)
{
var dto = Mapper.Map<ConsumptionData, ConsumptionDataDto>(consumptionData);
var refId = _personalProjectionRepository.AddPersonalProjectionRecord(dto);
consumptionData.ReferenceId = refId;
return PartialView("Reference", consumptionData);
}
else
{
throw new ValidationException();
}
}
The validation partial view:
#model PersonalProjection.Web.Models.ConsumptionData
#Html.ValidationSummary()
and the jquery:
$('form').submit(function () {
var form = $(this);
if (form.valid())
{
$.ajax({
url: form.attr("action"),
type: "POST",
dataType: "html",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
SiteId: $('#siteid').val(),
ElectricityConsumption: $('#electricityconsumption').val(),
ElectricitySpend: $('#electricityspend').val(),
GasConsumption: $('#gasconsumption').val(),
GasSpend: $('#gasspend').val()
}),
success: function (result) {
$('#rightPanelSection').html(result);
},
error: function (jqXHR) {
$('#validationSummary').html(jqXHR.responseText);
}
});
}
return false;
});
and the index.cshtml markup
<div class="panel panel-outcome">
#using (Html.BeginForm("Save", "Home", FormMethod.Post, (object)new { ID =
"projectionForm" }))
{
<div id="validationSummary"/>
<div id="topPanelSection" class="panel-section">
#Html.LabelFor(m => m.SiteId, new { id = "siteidlabel" })
#Html.TextBoxFor(m => m.SiteId, ViewBag.TextBoxDisabled ? (object)new { id =
"siteid", disabled = true, maxlength = 9, #class = "input-disabled", #Value =
ViewBag.SiteId } : new { id = "siteid", maxlength = 9 })
<span id="errorText" class="error-text" />
</div>
<div id="leftPanelSection" class="panel-section">
<div class="column-heading">
<span class="column-heading-left">Total Cost</span>
<span class="column-heading-right">Total Consumption</span>
</div>
<div class="panel-section-row">
#Html.LabelFor(m => m.ElectricitySpend, new { id = "electricitylabel" })
<span>£</span>
#Html.TextBoxFor(m => m.ElectricitySpend, new { #class = "textbox-right-
margin", id = "electricityspend" })
#Html.TextBoxFor(m => m.ElectricityConsumption, new { #class = "textbox-
left-margin", id = "electricityconsumption" })
<span>kWhs</span>
</div>
<div class="panel-section-row">
#Html.LabelFor(m => m.GasSpend, new { id = "gaslabel" })
<span>£</span>
#Html.TextBoxFor(m => m.GasSpend, new { #class = "textbox-right-margin", id =
"gasspend" })
#Html.TextBoxFor(m => m.GasConsumption, new { #class = "textbox-left-margin",
id = "gasconsumption" })
<span>kWhs</span>
</div>
<div class="panel-section-row">
<button type="reset" id="resetbutton">Reset Form</button>
<button type="submit">Generate Reference Id</button>
</div>
</div>
<div id="rightPanelSection" class="panel-section">
#Html.Partial("Reference", Model)
</div>
}
I'm fairly new to Ajax so this is probably a schoolboy error but here goes:
It's because when I use this jquery
$('#validationSummary').html(jqXHR.responseText);
To update this
<div id="validationSummary"/>
it doesn't like the closing tag & it messes up
Change to this
<div id="validationSummary">
</div>
And it works ok.

Jquery Accordion Validation Not working when rendering Partial View through $.ajax call

Hi friends,I am working on MVC 4 Razor and I am stuck in a situation
where Employee Personal Details form is to be filled in
steps(wizard)..for which i used jquery accordion control..for every
step i put an accordion..The html in each accordion section is
rendered from partial view through ajax call on every click of
respective accordion (i.e. <h3></h3> tag)..
On page load first/top accordion is active by default. My problem is
to restrict the user to click on next accordion until he/she fills the
presently active accordion correctly..
Here is my full code:
View:
#model XXX.ViewModels.PersonalDetailsViewModel
#{
ViewBag.Title = "PersonalDetails";
Layout = "~/Views/Shared/Template.cshtml";
}
#using (Html.BeginForm("Lifestyle", "Apply", FormMethod.Post, new { id = "personalDetailForm" }))
{
<div class="centerdiv margin_top20">
<div class="row">
#Html.ValidationSummary(true, "Please Correct the following errors:")
</div>
<div style="width: 1000px;">
<div id="Personalaccordion" class="acordion_div" style="padding: 10px; float: left;">
<h3 class="acordion_div_h3" onclick="javascript:PersonalModule.GetRenderingView('Apply/GetBasicDetailsView','personalDetailForm','BasicDetailsDiv');">
<p>
Basic Details<span id="BasicDetailsDivExp"></span>
</p>
</h3>
<div id="BasicDetailsDiv">
</div>
<h3 class="acordion_div_h3" onclick="javascript:PersonalModule.GetRenderingView('Apply/GetPersonalAddressView','personalDetailForm','PersonalAddressDiv');">
<p>
Address<span id="PersonalAddressDivExp"></span></p>
</h3>
<div id="PersonalAddressDiv">
</div>
</div>
<ul id="conlitue_ul" style="margin-top: 20px;">
<li style="margin-left: 140px;">
<input type="submit" class="compareBtn float_lt" value="Continue Buying >" id="continue" /></li>
</ul>
</div>
</div>
}
#Scripts.Render("~/bundles/PersonalDetails")
<script type="text/javascript">
PersonalModule.GetRenderingView('Apply/GetBasicDetailsView', '', 'BasicDetailsDiv');
</script>
My Controller:
public ActionResult PersonalDetails(int leadId)
{
var personalDetailsViewModel = LeadHelper.GetPersonalDetails(leadId);
return View(personalDetailsViewModel);
}
public ActionResult GetBasicDetailsView(PersonalDetailsViewModel personalDetailsViewModel)
{
if (personalDetailsViewModel.BasicDetails == null)
{
ModelInitializerHelper.InitilaizeBasicDetailsVModel(personalDetailsViewModel);
}
ModelInitializerHelper.InitializeBasicLookup(personalDetailsViewModel);
return PartialView("Personal/BasicDetails", personalDetailsViewModel);
}
public ActionResult GetPersonalAddressView(PersonalDetailsViewModel personalDetailsViewModel)
{
if (personalDetailsViewModel.PersonalAddressDetails == null)
{
ModelInitializerHelper.IntializePersonalAddressVModel(personalDetailsViewModel);
}
ModelInitializerHelper.InitializePersonalAddressLookup(personalDetailsViewModel);
return PartialView("Personal/PersonalAddress", personalDetailsViewModel);
}
My JS :
var PersonalModule = {
GetRenderingView: function (url, formId, containerID) {
var applicationurl = ApplicationRoot + '/' + url;
var objects = $('#BasicDetailsDivExp , #PersonalAddressDivExp' );
viewDivID = containerID;
GetAccordionView(applicationurl, formId, objects, containerID, 'accordion_plus', 'accordion_minus');
}
}
GetAccordionView: function (url, formId, objects, containerID, accordion_plus, accordion_minus) {
var formObjectData = null;
if (formId != undefined) {
formObjectData = $("#" + formId).serialize();
}
var renderView = function (data) {
$('#' + containerID).innerHtml = data;
}
ExpandAccordion(objects, containerID, accordion_plus, accordion_minus);
DoServerRequest(url, formObjectData, renderView);
}
ExpandAccordion: function (objects, spanIconID, accordion_plus, accordion_minus) {
var Objects = objects;
Objects.removeClass(accordion_minus);
Objects.addClass(accordion_plus);
$('#' + spanIconID + 'Exp').removeClass(accordion_plus).addClass(accordion_minus);
if (Browser.ie7) {
Objects.css("margin-top", "-22px");
}
}
DoServerRequest: function (url, data, funSuccess) {
$.ajax({
type: "POST",
url: url,
data: data,
async: false,
dataType: "json",
success: funSuccess,
error: function (errorResponse) {
if (errorResponse.readyState == 4 && errorResponse.status == 200) {
renderCurrentView(errorResponse.responseText)
}
else {
alert(errorResponse.responseText);
}
}
});
}
Please somebody help..I have heard lots of good thing about this forum
and this is my first Question...Thanks in advance..
I have removed my jquery validation attempt as it made the code
garbage thing Now I dont know what to write and where to write
If you are trying to validate data that has been added to form via Ajax after page load then you will need to use the rules method and add rules for these new elements. Jquery Validate has no way of knowing about them otherwise.
Example
Once you have loaded your new content via Ajax you need to find each element and add the necessary rules to them.
$('#yourDiv').find(".newElements").rules("add", {
required: true,
messages: {
required: "Bacon is required"
}
});
If you are using unobtrusive validate you may need to add your new elements to that also. See this SO question for more details.
Validating the Form
To check if the fields are valid, you will need to validate the form on click. This can be done using .validate(). You can then check if the form validated using .valid()
Example
$('#yourForm').validate();
if(!$('#yourForm').valid()) {
alert('Bacon is required');
}

JQuery Load using MVC3 #Url.Action does not pass parameters properly

I noticed that doing #Url.Action("myAction", new { param1 = 123, param2 = 456}) provides me with an invalid URL Home/myAction?param1=123&param2=456.
I am attempting to do
$("#myAjaxDiv").load(url);
But only param1 is getting populated in the action method.
When I remove the & and make it just & then it works, but doing a string replace is super hacky.
url = url.replace("&", "&");
Am I missing something here?
EDIT: Per request I'm including some of my sample app. (you can create a new MVC app and just add these quickly and see for yourself)
Controller:
public ActionResult AjaxTest(int? year, int? month)
{
ViewBag.Message = string.Format("Year: {0}, Month: {1}", year.HasValue ? year.ToString() : "no year", month.HasValue ? month.ToString() : "no month");
return PartialView("AjaxTest");
}
AjaxTest View:
#ViewBag.Message
Index View:
<script>
$(function () {
var url="";
$("#noParams").click(function () {
url = "Home/AjaxTest";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#yearParam").click(function () {
url = "Home/AjaxTest?year=2012";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#yearAndMonthParam").click(function () {
url = "Home/AjaxTest?year=2012&month=10";
$("#ajaxy").load(url)
$("#url").text(url);
});
$("#generated").click(function () {
url = "#(Url.Action("AjaxTest", new { year=2012, month=10}))";
$("#ajaxy").load(url);
$("#url").text(url);
});
});
</script>
<a id="noParams" href="#">No Params</a> <br />
<a id="yearParam" href="#">Year Param</a> <br />
<a id="yearAndMonthParam" href="#">Year and Month Param</a> <br />
<a id="generated" href="#">Generated</a> <br />
<div id="ajaxy">
</div>
<div>
URL: <span id="url"></span>
</div>
By default every content (which is not IHtmlString) emitted using a # block is automatically HTML encoded by Razor (see this Razor intro article Html Encoding section)
The Url.Action returns just a plain string so thats why the & gets encoded.
Use the Html.Raw if you don't want the encodeing:
url = "#(Html.Raw(Url.Action("AjaxTest", new { year=2012, month=10})))";
You can build the url in this way also.
var url = "#Url.Action("AjaxTest","YourControllerName")?year=2012&month=10";
$("#ajaxy").load(url);

ajax forms and results in popup window

I have a form in DoComment.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DT.KazBilet.Objects.PublicationComment>" %>
<div class="wrap">
<h4>Comment</h4>
<%using (Ajax.BeginForm("DoComment", "Publication", new {id = Model.Publication.OID, parentId = Model.OID},new AjaxOptions()))
{%>
<%=Html.TextAreaFor(x=>x.Text) %>
<%-- <textarea style="width: 100%; height: 152px;"></textarea>--%>
<input type="submit" value="Publish" class="btn ok_btn" />
<%}%>
</div>
This is my controller's action:
public JsonResult DoComment(PublicationComment model, int id, int parentId)
{
PublicationRepository.SaveComment(User.Identity.Name,id, parentId, model.Text);
return Json(new {
Message = "You comment on moderation"
});
}
I want that user clicks on Publish button then show popup window where will be written text from Message.
Can you help me(some code)?
Thanks.
You could subscribe to the OnSuccess javascript event in the AJAX options and then show the JSON result you have retrieved the way you like (new window, div, ...):
<% using (Ajax.BeginForm(
"DoComment",
"Publication",
new { id = Model.Publication.OID, parentId = Model.OID },
new AjaxOptions { OnSuccess = "onSuccess" })
) %>
and then you would define the onSuccess javascript function. Depending on whether you use jQuery or MicrosoftAjax the implementation of this function might slightly vary and more specifically the way to retrieve the JSON result.
For example if you are using MicrosoftAjax (obsolete now):
var onSuccess = function(e) {
var json = e.get_response().get_object();
alert(json.Message);
};
and if you are jQuery:
var onSuccess = function(json) {
alert(json.Message);
};

Resources