Uploading multiple files asp.net mvc4 in a single form - asp.net

I am trying to upload multiple files in one form and I have tried different ways.
This is my model
[MetadataType(typeof(MovieMetadata))]
public partial class Movie
{
}
class MovieMetadata
{
[ScaffoldColumn(false)]
public int id { get; set; }
[Required(ErrorMessage = "Title is required")]
public string title { get; set; }
[Required]
public DateTime releaseDate { get; set; }
public string storyline { get; set; }
public Binary poster { get; set; }
[ScaffoldColumn(false)]
public DateTime? duration { get; set; }
[ScaffoldColumn(false)]
public Binary trailer { get; set; }
}
One of the files that I want to upload is a video, so I put this tag in my Web.config to upload a file less than 1 GB, I put a big number because I will not know the size of the video
<httpRuntime targetFramework="4.5" maxRequestLength="102400"/>
My Controller is the following:
[HttpPost]
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
//saving the movie
OperationStatus opStatus = Repository.Save(movie);
if (!opStatus.Status)
{
return View("Error");
}
}
return View(movie);
}
Here is my View:
#model MoviesModel.Movie
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/MoviesLayout.cshtml";
}
#section createMovie{
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "createForm", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="gallMemberBox">
<div class="leftFormContent">
Movie Name
<div class="imgTmpl">
<!--solo hay que especificar el src de la imagen-->
<img src="../../Content/img/imgTest.jpg" alt="" />
</div>
</div>
<div class="rightFormContent">
<div>
#Html.LabelFor(model => model.title)
#Html.EditorFor(model => model.title)
#Html.ValidationMessageFor(model => model.title)
</div>
<div>
#Html.LabelFor(model => model.releaseDate)
#Html.EditorFor(model => model.releaseDate)
#Html.ValidationMessageFor(model => model.releaseDate)
</div>
<div>
#Html.LabelFor(model => model.duration)
<div>
<input type="text" id="time1" size="10" />
</div>
<pre><code></code></pre>
</div>
<div>
#Html.Label("Poster")
<input name="poster" value="C:" id="poster" type="file" />
</div>
<div>
#Html.Label("Trailer")
<input name="trailer" value="" id="trailer" type="file" />
</div>
<div>
#Html.LabelFor(model => model.storyline)
<textarea id="storyline"></textarea>
</div>
<input type="submit" value="Create" />
</div>
<div class="clearBoth"></div>
</div>
}
}
#section scripts{
#Scripts.Render("~/Scripts/jquery.timePicker.js")
<script type="text/javascript">
jQuery(function ()
{
// Default.
$("#time1").timePicker(
{
startTime: "00.00",
endTime: new Date(0, 0, 0, 6, 30, 0),
show24Hours: true,
separator: ':',
step: 3
}
);
})
</script>
}
#section styles{
#Styles.Render("~/Content/timePicker.css")
}
This includes the timepicker.js and css(inside the section style). Start time is to display the first option of time to select, the hour 00:00 and end time was 06:30, show24hours option hides from the control am and pm format, step: 3 means that the control will have all the hours in with the previous format with .3 minutes of difference. The sequence is like this: 00:00 00:03 00:06.... 06:27 06:30. I took it from this site https://github.com/perifer/timePicker/blob/master/index.htm
The problem is the following, when I tried to submit my form with all data(including the fields that are not required, first I got this message:
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.
I resolved it with this code:
public ActionResult Create([Bind(Exclude = "poster, trailer")]Movie movie, HttpPostedFileBase poster, HttpPostedFileBase trailer)
So I excluded poster and trailer field and I passed them to the controller like HttpPostedFileBase, thats work but my ModelState.IsValid is false. I thought that it could be a problem of my timepicker, so I excluded the duration field from the View and I tried again, and again I got false. I tried to put use this:
public ActionResult Create(FormCollection formCollection)
and with the post just came two keys, title and releaseDate. What about the others? What about ModelState.IsValid with the false value? Can I resolve my problem with a strong type and without the HttpPostedFileBase extra parameters that I put in the Create method of the controller?(Something like this: )
public ActionResult Create(Movie movie)
with the posted files included inside of it?

Related

I am getting null value in the server side from CheckBox in asp.net MVC

When I check the box, it shows it has a false value in the server side model but in the ajax call getting values it shows null values.
In the model class:
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
In the Razor Page:
<div class="row g-my-4">
<div class="col-md-10 g-pl-0">
<div class="row">
<div class="col-md-1"> </div>
<div class="col-md-7 g-pl-0 g-pr-0" id="IsBuyer">
<label>
#Html.CheckBoxFor(m=>m.IsBuyer)
#*#Html.CheckBoxFor(model => model.IsBuyer, new { id = "CheckBuyer" })*#
#*#Html.CheckBox("IsBuyer")*#
Buyer
</label>
</div>
</div>
</div>
</div>
I tried to use everything but nothing is working.
Getting data values to use ajax call
Here you can see the IsBuyer attribute is null = empty, and here on the server side it's getting false value however I have checked every check box but that's what I am getting back
Try to use usual BeginForm() block and post data like below:
#model Models.ViewModel
#using (Html.BeginForm())
{
<div class="form-group row">
<p>#Html.LabelFor(l => Model.IsBuyer) </p>
#Html.CheckBoxFor(r => Model.IsBuyer)
</div>
<input id="Button" type="submit" value="Save" />
}
In the controller code:
public IActionResult IndexTest()
{
var model = new ViewModel() { IsBuyer = true };
return View(model);
}
[HttpPost]
public IActionResult IndexTest(ViewModel data)
{
if (ModelState.IsValid)
{
// your code here...
}
return RedirectToAction("IndexTest", data);
}
// View data model class
public class ViewModel
{
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
// Additional propereties is defined here...
}

ASP.NET How to set Attributes at client side?

I'm trying to set some data at client side before I send it to server, but it give me no changes
The div contains data:
<div id="chanelValues" data-value="0" runat="server"></div>
The Checkbox which will give chanelValues div it's values
<input type="checkbox" onclick="dropdownClick(1, 'chanelValues')" />
dropdownClick func set chanelValues data-value to 1 success by js
But Server side give me chanelValues = 0
string chanelValues = this.chanelValues.Attributes["data-value"];
How Can I get updated data?
Thanks!
Maybe i get your question wrong but i will try...
You need a model as Interface between Server and Client
using System;
namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/introduction/adding-a-model
#model MvcMovie.Models.Movie
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
<h4>Movie</h4>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
#*Markup omitted for clarity.*#
</dl>
</div>
<p>
#Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
#Html.ActionLink("Back to List", "Index")
</p>
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model
You may take a look at the Update TargetID property
Controller:
public ActionResult SomeAction()
{
// you could return a PartialView here if you need more complex HTML fragment
return Content("<span>some content</span>", "text/html");
}
View:
<div id="result"></div>
<%= Ajax.ActionLink(
"Update div test",
"SomeAction",
new AjaxOptions { UpdateTargetId = "result" }
) %>

Validate function of IValidatableObject not working

I have a "Review" Class:
public class Review : IValidatableObject
{
public int ReviewId { get; set; }
[DisplayName("Digning Date")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
[Range(1, 10)]
public int Rating { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
public int RestaurantId { get; set; }
public virtual Restaurant Resturant { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var fields = new[]{ "Created"};
if(Created > DateTime.Now)
{
yield return new ValidationResult("Created date cannot be in the future.", fields);
}
if (Created < DateTime.Now.AddYears(-1))
{
yield return new ValidationResult("Created date cannot be to far in the past.", fields);
}
}
}
which uses Validate method of IValidatableObject to validate Create property. also this is my cshtml code:
#model OdeToFood.Models.Review
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#section scripts
{
<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>
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Review</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Created)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Created)
#Html.ValidationMessageFor(model => model.Created)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Rating)
#Html.ValidationMessageFor(model => model.Rating)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Body)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Body)
#Html.ValidationMessageFor(model => model.Body)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The Validate method simply check wether the year of date of Create is in present year(2012) or last year(2011). So if user enter 2000 as year he should get error: "Created date cannot be in the future.". But i does not work!
also this is my configuration in web.config:
<appSettings>
<add key="webpages:Version" value="1.0.0.0" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
also this my controller code:
public ActionResult Create()
{
return View(new Review());
}
//
// POST: /Reviews/Create
[HttpPost]
public ActionResult Create(int restaurantId, Review newReview)
{
try
{
//_db is my DBContext
var restaurant = _db.Restaurants.Single(r => r.RestaurantId == restaurantId);
newReview.Created = DateTime.Now;
restaurant.Reviews.Add(newReview);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch(System.Data.Entity.Validation.DbEntityValidationException ex)
{
return View();
}
}
What i must to do?
Thanks
It's getting called twice because once when you post and the model binder binds to newReview, and once when you call SaveChanges.
What you should do is when you post check if ModelState.IsValid= false, if so return View(newReview);
in addition your DbEntityValidationException should return View(newReview);
and lastly check out the action filter I wrote here - you don't need to have a try catch - simply use the attribute on your controller's method or register it on application startup like is done with HandleError
MapEntityExceptionsToModelErrorsAttribute

Remote Validate for DropDownList, MVC3, not firing in my case

I am using ASP.NET MVC3 and EF 4.1
I have two DropDownList in my Model, It is required and not duplicated too.
And I want the Remote validate function: ValidateDuplicateInsert get firing when user submit data. But I can NOT get the ValidateDuplicateInsert function firing.
Where am I wrong?
My Model
[Key]
public int CMAndOrgID { get; set; }
[Display(Name = "CM")]
[Required(ErrorMessage = "CM is required.")]
[Remote("ValidateDuplicateInsert", "CMAndOrg", HttpMethod = "Post", AdditionalFields = "CMID, OrganizationID", ErrorMessage = "CM is assigned to this Organization.")]
public int? CMID { get; set; }
[Display(Name = "Organization")]
[Required(ErrorMessage = "Organization is required.")]
public int? OrganizationID { get; set; }
public virtual CM CM { get; set; }
public virtual Organization Organization { get; set; }
The ValidateDuplicateInsert function in my CMAndOrg controller
[HttpPost]
public ActionResult ValidateDuplicateInsert(string cmID, string orgID)
{
bool flagResult = true;
foreach (CMAndOrg item in db.CMAndOrgs)
{
if (item.CMID.ToString() == cmID && item.OrganizationID.ToString() == orgID)
{
flagResult = false;
break;
}
}
return Json(flagResult);
}
And my View
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CMAndOrg</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CMID, "CM")
</div>
<div class="editor-field">
#Html.DropDownList("CMID", String.Empty)
#Html.ValidationMessageFor(model => model.CMID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OrganizationID, "Organization")
</div>
<div class="editor-field">
#Html.DropDownList("OrganizationID", String.Empty)
#Html.ValidationMessageFor(model => model.OrganizationID)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
There is a bug in MVC3 related to unobtrusive validation on dropdownlist. Please reference to this http://aspnet.codeplex.com/workitem/7629[^] link for more detail explaination.
Briefly, you can't use the same name for category collection and category field, so just change your collection name and update following line in your view
#Html.DropDownList("CategoryID", String.Empty)
with this
#Html.DropDownListFor(model => model.CategoryID, new SelectList((System.Collections.IEnumerable)ViewData["Categories"], "Value", "Text"))
Thanks again Henry He
Original link
http://www.codeproject.com/Articles/249452/ASP-NET-MVC3-Validation-Basic?msg=4330725#xx4330725xx

Asp.net MVC 3 "parameter conversion from type 'System.String' to type failed" when using SelectList Dropdown box

I'm stuck and after looking this up for hours, I think I need more eyeballs.
The situation is the following:
It's an Asp.Net MVC3 with Entity Framework 4 project. And I have two classes. One ConfigurationFile and another one Action. There is a one-to-many relationship between the two. Here is a simplified view on the code:
public class ConfigurationFile
{
[Key, Required]
[Column(TypeName = "uniqueidentifier")]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
[Column(TypeName = "uniqueidentifier")]
[Required]
public Guid ActionId { get; set; }
public virtual Models.Action Action { get; set; }
}
public class Action
{
[Key, Required]
[Column(TypeName = "uniqueidentifier")]
public Guid Id { get; set; }
[Required]
public string ActionValue { get; set; }
}
Then I want to create a new ConfigurationFile, and are my two controller methods (and at this point, this is 95% Visual Studio 10 generated code):
// db is my context class.
//
// GET: /Configuration/Create
public ActionResult Create()
{
ViewBag.ActionId = new SelectList(db.Actions, "Id", "ActionValue");
return View();
}
//
// POST: /Configuration/Create
[HttpPost]
public ActionResult Create(Models.ConfigurationFile configurationfile)
{
if (ModelState.IsValid)
{
configurationfile.Id = Guid.NewGuid();
db.ConfigurationFiles.Add(configurationfile);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ActionId = new SelectList(db.Actions, "Id", "ActionValue", configurationfile.ActionId);
return View(configurationfile);
}
And here is a snippet of my Create view:
#model MyProject.Areas.ConfigurationFile.Models.ConfigurationFile
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Configuration File</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ActionId, "Action")
</div>
<div class="editor-field">
#Html.DropDownList("ActionId", String.Empty)
#Html.ValidationMessageFor(model => model.ActionId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
When I open the Create page, I can clearly see that my dropdown for the Action class is fine (correct value -- the Action.Id -- and text -- Action.ActionValue -- ) but when I submit the form, I have the following error: "The parameter conversion from type 'System.String' to type 'MyProject.Models.Action' failed because no type converter can convert between these types."
Help please !!
Right now MVC has no way of connecting your dropdownlist from your view to the ActionId of your ConfigurationFile object.
I would try replacing this line:
#Html.DropDownList("ActionId", String.Empty)
for this
#Html.DropDownListFor(model => model.ActionId, ViewBag.ActionId)
Other than that, I can't think of what else you might have done wrong.
I hope that helps!
This is how I did to circumvent the problem. I just changed my controller this way:
Models.Action act = db.Actions.Find(configurationfile.ActionId);
ModelState.Clear();
configurationfile.Action = act;
TryValidateModel(configurationfile);
And after that, the validation was Ok. A bit hacky (and another possible hit on the DB), but at least, I can keep going.

Resources