I have to upload files and other data in a single submit of UploadFile.cshtml form
I have a base class which is the input of mvc action in home controller.
My base class, mvc action method and cshtml part with Razor script is given below
I have to get the file as byte array in the mvc action while submitting the UploadFile.cshtml form
My Base class
public class FileUpload
{
public string Name {get;set;}
public int Age {get;set;}
public byte[] Photo {get;set;}
}
MyMVCAction
[HttpPost]
public void UploadFile(FileUploadobj)
{
FileUploaddata=obj;
}
Mycshtmlform
#modelMVC.Models.FileUpload
#using(Html.BeginForm("UploadFile","Home",FormMethod.Post))
{
<fieldset>
<legend>File Upload</legend>
<div class="editor-label">
#Html.LabelFor(model=>model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model=>model.Age)
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.Age)
</div>
<div class="editor-label">
#Html.Label("UploadPhoto");
</div>
<div class="editor-field">
<input type="file" id="photo" name="photo"/>
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
I think better achieve it like this:
[HttpPost]
public ActionResult UploadFile(FileUpload obj)
{
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
obj.Photo = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
//return some action result e.g. return new HttpStatusCodeResult(HttpStatusCode.OK);
}
I hope it helps.
Related
This question already has answers here:
Asp.Net MVC: Why is my view passing NULL models back to my controller?
(2 answers)
Closed 5 years ago.
I'm new to c# and asp.net MVC and i'm working on a small project. I'm having an error on a create view using a view model. Whats happening is that after I complete the form when I submit it the data I populated isn't being received by the controller. Below is the code for my view, for my create on the controller and a view of the ModelView i'm using
//Controllers
// GET: Producto/Create
public ActionResult Create()
{
return View(ProductoViewModel.CargarListas());
}
// POST: Producto/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProductoViewModel producto)
{
Producto aux = producto.Producto;
aux.IdRecetaPreferida = producto.IdRecetaPreferida;
if (aux.Guardar())
{
return RedirectToAction(nameof(Index));
}
return View();
}
/*
* My view model im using on the view
*/
public class ProductoViewModel
{
public Producto Producto {get;set;}
[Display(Name = "Receta")]
public long IdRecetaPreferida { get; set; }
public Receta Receta { get; set; }
public List<Receta> Recetas { get; set; }
public ProductoViewModel()
{
this.Recetas = new List<Receta>();
this.Receta = new Receta();
}
public static ProductoViewModel CargarListas()
{
ProductoViewModel productoViewModel = new ProductoViewModel()
{
Recetas = Receta.TraerTodos()
};
return productoViewModel;
}
}
//My create view
#model WebApp.ViewModels.ProductoViewModel
<h2>Ingresar Producto</h2>
<hr />
<div class="row">
<div class="col-md-12">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group row">
<label asp-for="Producto.Nombre" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Producto.Nombre" class="form-control" placeholder="Nombre Producto" />
<span asp-validation-for="Producto.Nombre" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Producto.Descripcion" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Producto.Descripcion" class="form-control" placeholder="Una rica descripcion del producto" />
<span asp-validation-for="Producto.Descripcion" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="IdRecetaPreferida" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
#Html.DropDownListFor(m => m.IdRecetaPreferida, new SelectList(Model.Recetas, "Id", "Nombre"), new { #class = "custom-select" })
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
<a asp-action="Index">Volver</a>
</div>
</form>
</div>
</div>
If could point out my error would appreciate it. Below is a screenshot of the variable being debugged
I believe you forgot to specify that the form should send a POST request instead of a GET (default).
<form asp-action="Create" method="post">
Or you can remove the HttpPost attribute from the Create method.
I am new to ASP.NET MVC and I am having trouble updating the model data and then displaying it my view.
I currently have a MortgageCalculator class that I am using as a model.
public double loan_amount { get; set; }
public double interest { get; set; }
public int loan_duration { get; set; }
public int payments_year { get; set; }
Code for the controller is:
[httpGet]
public ActionResult M_Calculator()
{
var mortgageCalculator = new MortgageCalculator();
return View(mortgageCalculator);
}
[HttpPost]
public ActionResult M_Calculator(MortgageCalculator mortgageCalculator)
{
UpdateModel(mortgageCalculator);
return RedirectToAction("Results");
}
public ActionResult Results (MortgageCalculator mortgageCalculator)
{
return View(mortgageCalculator);
}
Code for my view is:
#using (Html.BeginForm())
{
<fieldset>
<legend>Mortgage Calculator</legend>
<div class="editor-label">
#Html.LabelFor(model => model.loan_amount)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.loan_amount)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.interest)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.interest)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.loan_duration)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.loan_duration)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.payments_year)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.payments_year)
</div>
<br />
<input type="submit" value="Calculate" />
</fieldset>
}
I want to make some calculations on the data that I receive from the user and then show the results in my Results view. I don't have any database. I just want to perform simple calculations on data and show the results. The solution seems to be pretty straight forward but I am stuck. I would appreciate any help.
Instead of redirect user to another action you should return your model with the result populated, like this:
[HttpPost]
public ActionResult M_Calculator(MortgageCalculator mortgageCalculator)
{
UpdateModel(mortgageCalculator);
return View("Results", mortgageCalculator);
}
If you don't want to create another view only to show the results, just remove the first parameter that indicates which view ASP.NET MVC should use, so, it will use the default view.
I am freshman in MVC, so I have some problems. I want to create Create Form, where I can insert some information such as Country, Region etc. and after to Serialize it to the file. But my Create Method get object wich don't have any indormation. So where I did mistake?
[HttpPost] // This is my Method which must Serialize class Address
public ActionResult Create(Address address)
{
if (ModelState.IsValid)
{
// Размещаем в XML данные
System.Xml.Serialization.XmlSerializer writer =
new System.Xml.Serialization.XmlSerializer(typeof(Address));
System.IO.StreamWriter file = new System.IO.StreamWriter(#"c:\MvcApp.xml");
writer.Serialize(file, address);
file.Close();
return RedirectToAction("Index");
}
return View(address);
}
This is my VIEW FILE
#model WorkWithAddresses.Models.Address
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Address</legend>
<div class="editor-label">
#Html.LabelFor(model=>model.country, "Country")
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.country)
#Html.ValidationMessageFor(model=>model.country)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.region, "Region")
<div>
<div class="editor-field">
#Html.EditorFor(model=>model.region)
#Html.ValidationMessageFor(model=>model.region)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Locality")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.locality)
#Html.ValidationMessageFor(model=>model.locality)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Street")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.street)
#Html.ValidationMessageFor(model=>model.street)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"House")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.houseNumber)
#Html.ValidationMessageFor(model=>model.houseNumber)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Building")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.buildingNumber)
#Html.ValidationMessageFor(model=>model.buildingNumber)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Apartment")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.apartmentNumber)
#Html.ValidationMessageFor(model=>model.apartmentNumber)
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List","Index")
</div>
// This is my class which I want to Serialize after user put information
[XmlRoot("Address")]
public class Address
{
#region Constructors
public Address()
{
}
#endregion
#region Public Member Variables
[XmlElement("AddressId")]
public int addressId; // Id адреса
[XmlElement("Country")]
public string country; // Страна
[XmlElement("Region")]
public string region; // Регион
[XmlElement("Locality")]
public string locality; // Населенный пункт
[XmlElement("Street")]
public string street; // Улица
[XmlElement("HouseNumber")]
public string houseNumber; // Номер дома
[XmlElement("BuildingNumber")]
public string buildingNumber; // Номер корпуса
[XmlElement("ApartmentNumber")]
public string apartmentNumber; // Номер квартиры
[XmlElement("Description")]
public Description description; // Описание адреса
#endregion
}
}
The View and the controller action code all look fine to me. The issue will be in the address class in the model. Mvc needs to have properties to deserialise the webforms post to.
public string Country { get; set; }
You should name these using title case for convention but it would still work if you kept them lowercase.
I am working on creating a blog with ASP.Net 4, MVC 3, Razor and C#.
There are 2 seperate tables. 1 for the actual blog post and a relationship table for categories.
The categories displays as a dropdown.
I want to add the ability to add a new category using Ajax so the user does not lose what they have already entered into the form.
What would be the best way to accomplish this?
Here is what I have right now.
Controller Code
public ActionResult Create()
{
ViewBag.category_id = new SelectList(_db.Categories, "id", "category_name");
return View();
}
Razor View
#model NPP.Models.News
#{
ViewBag.Title = "Create News Item";
}
<h2>Create News Item</h2>
<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>News</legend>
<div class="editor-label">
#Html.LabelFor(model => model.news_title, "Title")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.news_title)
#Html.ValidationMessageFor(model => model.news_title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.news_content, "Content")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.news_content)
#Html.ValidationMessageFor(model => model.news_content)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.news_teaser, "Teaser (optional)")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.news_teaser)
#Html.ValidationMessageFor(model => model.news_teaser)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.category_id, "Category")
</div>
<div class="editor-field">
#Html.DropDownList("category_id", String.Empty)
#Html.ValidationMessageFor(model => model.category_id)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Thanks for any help in advance. My layout page includes jquery which I would prefer to use.
Add another controler method to return you a list of categories, something like:
public JsonResult Categories()
{
return Json(DB.GetCategorys(), JsonRequestBehavior.AllowGet);
}
Then on the client side, use ajax to get your categories and bind them to your drop down, something like:
$.ajax({
url: 'http://myserver/myapp/mycontroller/Categories',
success: function(data) {
$('#dropCategorys').html('');
$.each(data, function(i, e) {
$('#dropCategorys').append('<option value="' +
e.category_id + '">' + e.category_name + '</option>');
}
}
});
This won't save your current selected item, but you can always check that before clearing the list, and reset it afterwards.
Creating the Category separately via AJAX is not your only option. You could then have a view model like this:
public class CategoryViewModel
{
public string name { get; set; }
public int id { get; set; }
}
public class CreateNewsViewModel
{
public string news_title { get; set; }
public string news_content { get; set; }
public string news_teaser { get; set; }
public string CategoryViewModel category { get; set; }
}
Change your view at the category field:
<div class="editor-label">
#Html.LabelFor(model => model.category, "Category")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.category.id, ViewBag.category_id)
#Html.EditorFor(model => model.category.name) <!-- only show when creating a new category -->
#Html.ValidationMessageFor(model => model.category)
</div>
Then your action would look something like this:
[HttpPost, ActionName("Create")]
public ActionResult DoCreate(CreateNewsViewModel model)
{
if (ModelState.IsValid)
{
if (model.category.id == 0)
{
// create your new category using model.category.name
}
// create an entity from the model and save to your database
return RedirectToAction("Index", "News"); // do whatever you wish when you're done
}
return View("Create", model); // show Create view again if validation failed
}
This is more or less off the top of my head so let me know if I bollocks'ed any parts up.
I am trying to allow a user to upload an image to our website and I'm not quite sure about how to use this. I have tried to use multiple types to define the image, including System.Drawing.Image and HttpPostedFileWrapper but the #Html.EditorFor always (understandably) brings up its attributes as fields to edit.
In my view I did have, instead of #Html.EditorFor I did have <input type="file" name="imageToUpload" /> but it didn't get taken through to my view as part of the Model? I am quite new to MVC so I am hoping it is something trivial.
Here is my View:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>New Image</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Image)
</div>
<div class="editor-field">
<input type="file" name="imageToUpload" />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
My Controller:
[HttpPost]
public ActionResult CreateImage(string brand, string collection, ImageEditViewModel imageEditViewModel)
{
string fileName = Guid.NewGuid().ToString();
string serverPath = Server.MapPath("~");
string imagesPath = serverPath + String.Format("Content\\{0}\\Images\\", Helper.Helper.ResolveBrand());
string newLocation = Helper.Helper.SaveImage(fileName, imagesPath, imageEditViewModel.Image.InputStream)
Image image = new Image
{
Collection = ds.Single<Collection>(c => c.Season == collection
&& c.Brand.Name == brand),
Description = imageEditViewModel.Description,
Location = "newLocation",
Order = Helper.Helper.GetImageOrder(brand, collection)
};
ds.InsertOnSubmit<Image>(image);
ds.SubmitChanges();
return RedirectToAction("Brand");
}
And finally the ViewModel:
public class ImageEditViewModel
{
public int CollectionId { get; set; }
public string Description { get; set; }
public HttpPostedFileWrapper Image { get; set; }
public int Order { get; set; }
}
Ensure to specify the correct enctype="multipart/form-data" on your form or you won't be able to upload files:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>New Image</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ImageToUpload)
</div>
<div class="editor-field">
<input type="file" name="imageToUpload" />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
And if you wanted to use an EditorFor helper to generate the file input you could use the following:
<div class="editor-label">
#Html.LabelFor(model => model.ImageToUpload)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ImageToUpload)
</div>
and then define a custom editor template for the HttpPostedFileBase type (see below that you need to modify your model to use this type actually). So the editor template in ~/Views/Shared/EditorTemplates/HttpPostedFileBase.cshtml:
#model HttpPostedFileBase
#Html.TextBox("", null, new { type = "file" })
and on your view model use the HttpPostedFileBase type and make sure that the name of the property matches the name of the file input on your form:
public class ImageEditViewModel
{
public int CollectionId { get; set; }
public string Description { get; set; }
public HttpPostedFileBase ImageToUpload { get; set; }
public int Order { get; set; }
}
Also make sure to checkout the following blog post.