error "Index was out of range" in razor application - asp.net

I had this error when use upload file with razor page :
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
the error occurred here
var uploadedFile = Request.Files[0];
Controller:
[HttpPost]
public ActionResult Create(Category category)
{
if (ModelState.IsValid)
{
var fileSavePath = "";
var fileName = "";
var uploadedFile = Request.Files[0];
fileName = Path.GetFileName(uploadedFile.FileName);
fileSavePath = Server.MapPath("../../Uploads/" + fileName);
uploadedFile.SaveAs(fileSavePath);
db.Categories.Add(category);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
View:
#using (Html.BeginForm("Create", "Category", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<div class="editor-label">
#Html.LabelFor(model => model.Path)
</div>
<div class="editor-field create-Bt3">
#FileUpload.GetHtml(
initialNumberOfFiles: 1,
allowMoreFilesToBeAdded: false,
includeFormTag: false,
uploadText: "Upload")
</div>
}

The error means, that the Request.Files collection does not contain any item.
You can check with the Count property for the number of files uploaded:
if (Request.Files.Count > 0) {
var uploadedFile = Request.Files[0];
}
Check with fiddler what the browser is sending - maybe its an issue with the FileHelper

Related

Get 0 vaule return to controller from viewbag dropdown list

I'm having the problem where I get 0 value return from my view bag Drop-down list. I don't have any problem for displaying list to my drop-down but when I submit the form, both of my drop down return 0 values to my controller. even, I selected the list.
Here is my code for Add controller.
public ActionResult Add()
{
List<City> lstcCities = db.Cities.ToList();
lstcCities.Insert(0, new City { Id = 0, Name = "Choose City" });
List<County> lstCounties = db.Counties.ToList();
lstCounties.Insert(0, new County { Id = 0, Name = "Choose County" });
ViewBag.CityId = new SelectList(lstcCities, "Id", "Name");
ViewBag.CountyId = new SelectList(lstCounties, "Id", "Name");
var category = db.Categories.ToList();
var viewModel = new AdsViewModel
{
Category = category,
};
return View("Add", viewModel);
}
Here is my view code
<div class="form-group">
#Html.LabelFor(m => m.Ads.City.Id)
#Html.DropDownList("CityId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Ads.CityId, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.Ads.County.Name)
#Html.DropDownList("CountyId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Ads.CountyId, "", new { #class = "text-danger" })
</div>
Here is my post action.
[HttpPost]
public ActionResult Add(Ads ads, IEnumerable<HttpPostedFileBase> images,
HttpPostedFileBase ImageFile)
{
//Ensure model state is valid
if (ModelState.IsValid)
{
//check if images is null
if (images != null)
{
var imageList = new List<AdsImage>();
foreach (var image in images) //Loop for images for multiple uploading.
{
using (var br = new BinaryReader(image.InputStream))
{
var data = br.ReadBytes(image.ContentLength);
var img = new AdsImage { AdsId = ads.Id };
img.ImageData = data;
imageList.Add(img);
}
}
ads.AdsImage = imageList;
}
//Upload poster
////Add image to database
string fileName = Path.GetFileNameWithoutExtension(ImageFile.FileName);
string extension = Path.GetExtension(ImageFile.FileName);
fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
ads.Poster = "/Images/Ads_Image/" + fileName;
fileName = Path.Combine(Server.MapPath("/Images/Ads_Image/"), fileName);
ImageFile.SaveAs(fileName);
ViewBag.CityId = new SelectList(db.Cities, "Id", "Name", ads.CityId);
ViewBag.CountyId = new SelectList(db.Counties, "Id", "Name", ads.CountyId);
var userID = User.Identity.GetUserId();
ads.ApplicationUserId = userID;
ads.PostDate = DateTime.Now;
db.Adses.Add(ads);
db.SaveChanges();
}
}
Anyone knows how to fix this problem or can help me with this problem
Thank you in advance for any helps.

Ajax Form returns null on CSV upload

The way this is setup is,
-There is a View which takes the CSV upload
-There is a Controller Partial View Action which is supposed to retrieve the parse the CSv and read the objects from the CSV and pass that back to the PArtial View.
-The Partial View is than SUPPOSED to render on the page with all the records.
But apparently the bulkClients object appears null.
Here is the Controller :-
public ActionResult UploadBulkClients()
{
return View();
}
// [HttpPost]
public PartialViewResult _UploadBulkClients(HttpPostedFileBase bulkClients)
{
if (bulkClients != null)
{
try
{
StreamReader reader = new StreamReader(bulkClients.InputStream);
while (reader != null)
{
var csv = new CsvReader(reader);
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
newRecord.Add(new ClientAgencyViewModel()
{
Id = UrbanLighthouse.Shared.Statics.NewUniqueGUID(),
ReferenceNo = csv["ReferenceNo"].ToString(),
FirstName = csv["FirstName"].ToString(),
MiddleName = csv["MiddleName"].ToString(),
LastName = csv["LastName"].ToString(),
StreetAddress = csv["StreetAddress"].ToString(),
City = csv["City"].ToString(),
PostalCode = csv["PostalCode"].ToString(),
Province = Guid.Parse(csv["Province"].ToString()),
Phone = csv["Phone"].ToString(),
Email = csv["Email"].ToString()
});
}
foreach (var item in newRecord)
{
if (repository.DoesEmailExist(item.Email) == true)
{
item.Email = item.Email + " : " + "Invalid Email Address";
}
else
{
item.Email = item.Email + " : " + "This Email is Good";
}
}
}
return PartialView(newRecord);
}
catch (System.IO.IOException e)
{
return PartialView(e);
}
}
else
{
newRecord.Add(new ClientAgencyViewModel()
{
ReferenceNo = "Empty",
FirstName = "Empty",
MiddleName = "Empty",
LastName = "Empty",
StreetAddress = "Empty",
City = "Empty",
PostalCode = "Empty",
Province = Guid.Empty,
Phone = "Empty",
Email = "Empty"
});
return PartialView(newRecord);
}
}
Here is how the View is layed out :-
#model string
#{
Layout = "~/Views/Shared/_LayoutAnonymous.cshtml";
AjaxOptions options = new AjaxOptions
{
UpdateTargetId = "uploadList",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST"
};
}
<div>
#using (Ajax.BeginForm("_UploadBulkClients", "Client",options, new { enctype = "multipart/form-data" , role = "form", #class = Css.Form, #id = "formLogin" , action = "/Client/_UploadBulkClients" }))
{
<div class="#Css.FormGroup">
<h1>Client Bulk Upload</h1>
<div class="#Css.InputGroup">
<label>Upload CSV File</label>
<input type="file" name="postedFile" />
</div>
<div class="#Css.InputGroup">
#Html.Submit("Submit")
</div>
</div>
}
</div>
<div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Reference No</th>
<th>FirstName</th>
<th>MiddleName</th>
<th>LastName</th>
<th>Phone</th>
<th>Email</th>
<th>StreetAddress</th>
<th>City</th>
<th>PostalCode</th>
<th>Province</th>
</tr>
</thead>
<tbody id="uploadList">
#Html.Action("_UploadBulkClients","")
</tbody>
</table>
</div>
When the HttpPost decorator is left on top of the PartialView Method, it gives an Error in the View #Html.Action("_UploadBulkClients","") saying that the _UploadBulkClients Action method does not exist.
EDIT:-
It seems that the upload is not posting the csv file, and I would not understand why that would be, as the Ajax form seems to be the way it is supposed to be.
Any help would be appreciated !
With the help of Stephen, I was able to figure out the answer, it had to be done using JavaScript and not AjaxOptions in C#.
Here are the steps just in case someone encounters something similar :-
1. The Controller Method which returns the form
public ActionResult UploadBulkClients()
{
return View();
}
2. The form has to be a simple form and not an Ajax form. I used Html Helpers here:
#using (Html.BeginForm("_UploadBulkClients", "Client",null, FormMethod.Post , new { enctype = "multipart/form-data" , role = "form", #class = Css.Form, #id = "uploadForm" }))
{
<div class="#Css.FormGroup">
<h1>Client Bulk Upload</h1>
<div class="#Css.InputGroup">
#Html.LabelFor(m=>m.File)
#Html.TextBoxFor(m=>m.File, new { type= "file"})
</div>
<div class="#Css.InputGroup">
#Html.Submit("Submit")
</div>
</div>
}
3. The next part is the controller method which return the partial view.
[HttpPost]
public PartialViewResult _UploadBulkClients(HttpPostedFileBase file)
{
if (file != null)
{
try
{
using (var reader = new StreamReader(file.InputStream))
using (var csv = new CsvReader(reader))
{
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
newRecord.Add(new ClientAgencyViewModel()
{
Id = UrbanLighthouse.Shared.Statics.NewUniqueGUID(),
ReferenceNo = csv["ReferenceNo"],
FirstName = csv["FirstName"].ToString(),
MiddleName = csv["MiddleName"].ToString(),
LastName = csv["LastName"].ToString(),
StreetAddress = csv["StreetAddress"].ToString(),
City = csv["City"].ToString(),
PostalCode = csv["PostalCode"].ToString(),
ProvinceText = csv["Province"].ToString(),
Phone = csv["Phone"].ToString(),
Email = csv["Email"].ToString()
});
}
foreach (var item in newRecord)
{
if (repository.DoesEmailExist(item.Email) == true)
{
item.Email = item.Email + " : " + "Email Address Already Exists";
}
else
{
item.Email = item.Email + " : " + "This Email is Good";
}
}
}
return PartialView(newRecord);
}
catch (System.IO.IOException e)
{
return PartialView(e);
}
}
else
{
newRecord.Add(new ClientAgencyViewModel()
{
ReferenceNo = "Empty",
FirstName = "Empty",
MiddleName = "Empty",
LastName = "Empty",
StreetAddress = "Empty",
City = "Empty",
PostalCode = "Empty",
ProvinceText = "Empty",
Phone = "Empty",
Email = "Empty"
});
return PartialView(newRecord);
}
}
4. The next part is the partial View which renders the output from the controller method.
#model List<WebPlatform.ViewModels.ClientAgencyViewModel>
#foreach (var item in Model)
{
<tr>
<td>#item.ReferenceNo</td>
<td>#item.FirstName</td>
<td>#item.MiddleName</td>
<td>#item.LastName</td>
<td>#item.Phone</td>
<td>#item.Email</td>
<td>#item.StreetAddress</td>
<td>#item.City</td>
<td>#item.PostalCode</td>
<td>#item.ProvinceText</td>
</tr>
}
5. And last but not the least the Ajax functionality written within the JavaScript because AjaxOptions will not work in this particular situation.
$('#uploadForm').submit(function(e) {
e.preventDefault();
var formdata = new FormData($(this).get(0));
$.ajax({
url: '#Url.Action("_UploadBulkClients","Client")',
type: 'POST',
data: formdata,
processData: false,
contentType: false,
success: function (response) {
$('#uploadList').html(response);
}
},
);
});

Testing Model is valid

Working on a web app, MVC 5 in VS 2015.
Here is my model:
public class InfoFormulaireEmployeModele
{
[Required(ErrorMessage =" *You must provide a date")]
[RegularExpression("^[0-9]{8}$", ErrorMessage ="The date must be of the format AAAAMMJJ")]
public string dateEvenementInitial { get; set; }
}
When I try to enter some invalid input, let's say '12ab' , it works fine, I'm back on the page with the error message.
Here is my view:
#using PortailLibreService.Models
#model InfoFormulaireEmployeModele
#{
ViewBag.Title = "ChampsFormulaireInvalidite";
}
#using (Html.BeginForm())
{
<div class="editor-field">
<b>Initial event </b><br>
<p>When did the initial event occured?</p>
#Html.TextBoxFor(x => x.dateEvenementInitial, new { #placeholder = "AAAAMMJJ" }) #Html.ValidationMessageFor(x => x.dateEvenementInitial, null, new { #class = "error" })
</div>
<input type="submit" name="Save" value="Submit" />
}
I wanted to create a unit test to be sure that my model wouldn't be valid with an invalid date entry.
Here is my unit test:
[TestMethod]
public void testRetourPossibleInvalide()
{
InfoFormulaireEmployeModele modelDuplicat = new InfoFormulaireEmployeModele();
modelDuplicat.dateEvenementInitial = "abc";
InvFormController controlleur = lib.getController("100237");
var result = controlleur.ChampsFormulaireInvalidite(modelDuplicat);
Assert.AreEqual(false, controlleur.ModelState.IsValid);
}
For some reason the test fails, controlleur.ModelState.IsValid is true while it should be false. If I test it with only numerical values it's fine. For example, this test passed:
[TestMethod]
public void testRetourPossibleInvalide()
{
InfoFormulaireEmployeModele modelDuplicat = new InfoFormulaireEmployeModele();
modelDuplicat.dateRetourPossible = "129";
InvFormController controlleur = lib.getController("100237");
var result = controlleur.ChampsFormulaireInvalidite(modelDuplicat);
Assert.AreEqual(false, controlleur.ModelState.IsValid);
}
controlleur.ModelState.IsValid is false while running the test, so the test passes.
I tried to put a breakpoint inside my controller method but I can't reach it while debugging..
You would have to act as the framework, which usually does all the checking for you.
[TestMethod]
public void testRetourPossibleInvalide() {
var model = new InfoFormulaireEmployeModele();
model.dateEvenementInitial = "abc";
var controller = new InvFormController();
var bindingContext = new ModelBindingContext() {
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),
ValueProvider = new NameValueCollectionValueProvider(new NameValueCollection(), CultureInfo.InvariantCulture)
};
var boundModel = new DefaultModelBinder().BindModel(new ControllerContext(), bindingContext);
controller.ModelState.Clear();
controller.ModelState.Merge(bindingContext.ModelState);
var result = controller.ChampsFormulaireInvalidite(model);
Assert.AreEqual(false, controller.ModelState.IsValid);
}

How update/edit uploaded files in asp.net mvc 5 without redundancy?

I have a problem with update data in Asp.net MVC 5 with Razor Engine .
my Update code works fine but I have some problems with it . When I update Image , old image stays in Images folder. I want to delete old image if it changed . and I want to stay old image if it didn't change .
How can I do it ?
Thanks a lot for any help
I don't know how write if statement for this :/
CarouselRepositories.cs
public bool Update(NP1.Models.Carousel entity, bool autoSave = true)
{
try
{
db.Carousels.Attach(entity);
db.Entry(entity).State = System.Data.Entity.EntityState.Modified;
if (autoSave)
return Convert.ToBoolean(db.SaveChanges());
else
return false;
}
catch
{
return false;
}
}
Admin controller
[HttpGet]
public ActionResult EditCarousel(int id)
{
var load = db.Carousels.Find(id);
return View(load);
}
[HttpPost]
public ActionResult EditCarousel(Carousel carousel, HttpPostedFileBase UploadImage)
{
CarouselRepositories blCarousel = new CarouselRepositories();
string path = "";
var fileName = "";
var rondom = "";
if (UploadImage != null)
{
fileName = Path.GetFileName(UploadImage.FileName);
rondom = Guid.NewGuid() + fileName;
path = System.IO.Path.Combine(
Server.MapPath("~/Images/Carousel"), rondom);
carousel.CarouselImage = rondom;
}
if (ModelState.IsValid)
{
UploadImage.SaveAs(path);
carousel.CarouselImage = rondom;
if (blCarousel.Update(carousel))
{
return JavaScript("alert('Carousel slide added');");
}
else
{
return JavaScript("alert('didn't add');");
}
}
else
{
return JavaScript("alert('Error');");
}
}
EditCarousel.cshtml:
#model NP1.Models.Carousel
#{
ViewBag.Title = "EditCarousel";
Layout = "~/Views/Admin/AdminLayout.cshtml";
}
#using (Html.BeginForm("EditCarousel", "Admin", FormMethod.Post, new { enctype = "multipart/form-data", id = "myUploadForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.CarouselID)
<div class="form-group">
#Html.LabelFor(model => model.CarouselSubject, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CarouselSubject)
#Html.ValidationMessageFor(model => model.CarouselSubject)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CarouselInfo, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CarouselInfo)
#Html.ValidationMessageFor(model => model.CarouselInfo)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CarouselImage, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.EditorFor(model => model.CarouselImage)*#
#Html.ImageFor(model => model.CarouselImage, new {width="300"},"","Images","Carousel")
#Html.Upload("UploadImage")
#Html.HiddenFor(model => model.CarouselImage)
</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>
</div>
}
Updated Amin Controller :
[HttpPost]
public ActionResult EditCarousel(Carousel carousel, HttpPostedFileBase UploadImage)
{
CarouselRepositories blCarousel = new CarouselRepositories();
string path = "";
var fileName = "";
var rondom = "";
if (UploadImage != null)
{
fileName = Path.GetFileName(UploadImage.FileName);
rondom = Guid.NewGuid() + fileName;
path = System.IO.Path.Combine(
Server.MapPath("~/Images/Carousel"), rondom);
carousel.CarouselImage = rondom;
}
else
{
fileName = carousel.CarouselImage;
path = System.IO.Path.Combine(
Server.MapPath("~/Images/Carousel"), fileName);
}
if (ModelState.IsValid)
{
UploadImage.SaveAs(path); // I got error in this line
carousel.CarouselImage = rondom;
if (blCarousel.Update(carousel))
{
return JavaScript("alert('Carousel slide added');");
}
else
{
return JavaScript("alert('didn't add');");
}
}
else
{
return JavaScript("alert('Error');");
}
}
Assuming you want to delete the current file if the value of UploadImage is not null in the POST method, then you can use the System.IO.File.Delete method
private const string _ImagesPath = "~/Images/Carousel";
[HttpPost]
public ActionResult EditCarousel(Carousel carousel, HttpPostedFileBase UploadImage)
{
if (ModelState.IsValid)
{
CarouselRepositories blCarousel = new CarouselRepositories();
if (UploadImage != null)
{
// Delete exiting file
System.IO.File.Delete(Path.Combine(Server.MapPath(_ImagesPath), carousel.CarouselImage));
// Save new file
string fileName = Guid.NewGuid() + Path.GetFileName(UploadImage.FileName);
string path = Path.Combine(Server.MapPath(_ImagesPath), fileName);
UploadImage.SaveAs(path)
carousel.CarouselImage = fileName;
}
if (blCarousel.Update(carousel))
{
....
}
else
{
....
}
}
else
{
....
}
}

BeginCollectionItem() gives only lastly appended item for PostBack

InquiryOrderViewModel
public class InquiryOrderViewModel
{
public InquiryOrder InquiryOrder { get; set; }
public List<InquiryOrderDetail> InquiryOrderDetails { get; set; }
}
InquiryOrderIndex View and the Script to add items
#model eKnittingData.InquiryOrderViewModel
#using (Html.BeginForm("Save", "InquiryOrder"))
{
<div id="editorRows">
#foreach (var item in Model.InquiryOrderDetails)
{
Html.RenderPartial("_DetailEditorRow", item);
}
</div>
#Html.ActionLink("Add another...", null, null, new { id = "addItem" })
<div class="col-md-6"> <input type="submit" value="Save" class="btn btn-success" /> </div>
}
<script>
$('#addItem').click(function (e) {
e.preventDefault();
var isExist = false;
$('.editorRow').each(function () {
if ($(this).children('.class01').val() == 0 || $(this).children('.class02').find("option:selected").text() == "Select") {
isExist = true;
return false;
}
});
if (isExist == false) {
$('.editorRow').each(function () {
$(".editorRow").children().attr("disabled", "disabled");
});
$.ajax({
url: '#Url.Action("BlankEditorRow", "InquiryOrder")',
cache: false,
success: function (data) {
$("#editorRows").append(data);
}
});
}
});
</script>
DetailEditorRow PartialView
#model eKnittingData.InquiryOrderDetail
#using eKnitting.Helpers
#using (Html.BeginCollectionItem("InquiryOrderDetails"))
{
<div class="editorRow">
#Html.DropDownListFor(a => a.ComponentId, (SelectList)ViewBag.CompList, "Select", new { Class = "class02" })
#Html.DropDownListFor(a => a.DesignCodeId, (SelectList)ViewBag.DCodeList, "Select", new { Class = "class03" })
#Html.TextBoxFor(a => a.NoOfParts, new { Class = "class01" })
delete
</div>
}
ActionResult which returns PartialView
public ActionResult BlankEditorRow()
{
var objContext = new KnittingdbContext();
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return PartialView("_DetailEditorRow", new InquiryOrderDetail());
}
ActionResult for 'GET'
var objContext = new KnittingdbContext();
var newIovm = new InquiryOrderViewModel();
var newIo = new InquiryOrder();
//initial item
var newIoD = new List<InquiryOrderDetail>
{
new InquiryOrderDetail()
};
newIovm.InquiryOrder = newIo;
newIovm.InquiryOrderDetails = newIoD;
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return View(newIovm);
ActionResult for 'POST'
public ActionResult Save(InquiryOrderViewModel inquiryOrderViewModel)
{
.................
}
When i click the add button im able to add items dynamically. But for PostBack it gives me only the lastly appended item. I checked it by putting a break point on post ActionResult. How can i get the whole collection for PostBack? Where did i go wrong? All help appreciated. Thanks!
Your scripts sets a variable var isExist = false;. When you add a new item, you check if the value is false (which it is if you got that far) and then disable all existing inputs.
Disabled form controls do not post back, hence you only get the values for the last row you have added.
Its unclear why you would want to disable them, but if you want to prevent editing of existing rows, the make them readonly
$(".editorRow").children().prop("readonly", true);

Resources