I have just tried a lot of things that I found but at the end nothing successfull.
First I have the next code that just do the things ok but dont save the image.
What should I do to save an image into a varbinarymax? and how to show them to the view next?
view:
<div class="form-group">
#Html.LabelFor(model => model.Logo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.EditorFor(model => model.Logo, new { htmlAttributes = new { #class = "form-control" } })*#
#Html.TextBoxFor(model => model.Logo, new { type = "file" })
#Html.ValidationMessageFor(model => model.Logo, "", new { #class = "text-danger" })
</div>
</div>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,Name,Address,Description,Mail,Phone,Small_Description")] School school)
{
if (ModelState.IsValid)
{
db.School.Add(school);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(school);
}
Model:
public partial class School
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public School()
{
this.Product = new HashSet<Product>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Description { get; set; }
public string Mail { get; set; }
public int? Phone { get; set; }
public byte[] Logo { get; set; }
public string Small_Description { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Product> Product { get; set; }
}
Change View First to This:
#using (Html.BeginForm("Create", "Schole", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.LabelFor(model => model.Logo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Logo, new { type = "file" })
<input type="submit" value="submit" />
</div>
</div>
}
Change Action To This:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,Name,Address,Description,Mail,Phone,Small_Description")] School school, HttpPostedFileBase Logo)
{
if (ModelState.IsValid)
{
using (var memoryStream = new MemoryStream())
{
Logo.InputStream.CopyTo(memoryStream);
school.Logo = memoryStream.ToArray();
}
db.School.Add(school);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(school);
}
}
Now This Logo Save It.
As you don't have posted complete form, here is complete code to upload image and save into DB.
you form must have enctype property.
#using (Html.BeginForm("Index","Home",FormMethod.Post, new{ enctype = "multipart/form-data" }))
{
//your other code
<input type="file" name="logo" />
<input type="submit" value="Save" />
}
And inside your action.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,Name,Address,Description,Mail,Phone,Small_Description")] School school)
{
if (ModelState.IsValid)
{
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files["logo"].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files["logo"].ContentLength);
}
school.Logo=fileData;
db.School.Add(school);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(school);
}
It will save file in your Db.
Related
In my MVC5 application I have two model Order and File as following:
public class Order
{
public int OrderID { get; set; }
public string OrderName{ get; set; }
}
public class File
{
public HttpPostedFileBase[] files { get; set; }
}
I want edit objects of both classes in single view, so I create parent class:
public class MainContext
{
public Order Order { get; set; }
public File File { get; set; }
}
In the view I have this:
#using (Html.BeginForm("Create", "Order", FormMethod.Post, new { encType = "multipart/form-data" }))
#Html.AntiForgeryToken()
<div class="form-group">
<label>OrderName</label>
#Html.EditorFor(model => model.Order.OrderName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Order.OrderName, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.File.files, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.File.files, "", new { #type = "file", #multiple = "multiple", })
#Html.ValidationMessageFor(model => model.File.files, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<input type="submit" value="submit" class="btn btn-success btn-lg btn-block" />
</div>
The Controller
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OrderName")] Order order, HttpPostedFileBase[] files)
{
if (ModelState.IsValid)
{
db.Order.Add(order);
db.SaveChanges();
if (files != null)
{
foreach (HttpPostedFileBase file in files)
{
if (file != null)
{
var InputFileName = Path.GetFileName(file.FileName);
var ServerSavePath = Path.Combine(Server.MapPath("~/UploadedFiles/") + InputFileName);
file.SaveAs(ServerSavePath);
}
}
}
return RedirectToAction("Index");
}
}
Now the problem .. after I submit the form I got order values in Create action BUT files is always NULL !
What I miss
Thanks in advance
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(MainContext model)
{
// here fetch values from model.Order and model.File
}
Instead of fetching two models separately call "MainContext" class in post action, from that you can get all the view values....
is there a way where I can replace multiple strings e.g.. hot , cold , good, with ###?
The text field
div class="form-group">
#Html.LabelFor(model => model.Comment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comment, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
Controller
public ActionResult Create()
{
return View(new Charity());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,DisplayName,Date,Amount,Comment")] Charity charity)
{
if (ModelState.IsValid)
{
db.Donations.Add(charity);
db.SaveChanges();
return RedirectToAction("Additionalinfo", "Charities");
}
return View(charity);
}
Model
public class Charity
{
public int ID { get; set; }
[RegularExpression(#"^[a-zA-Z]+$", ErrorMessage = "Use letters only please")]
public string DisplayName { get; set; }
[DataType(DataType.Currency)]
[Range(2, Int32.MaxValue, ErrorMessage = "Atleast £2.00 or a whole number please")]
public int Amount { get; set; }
public Double TaxBonus { get; set; }
public String Comment { get; set; }
}
Can I replace multiple texts with one code function or does it have to be individually for each string?? I am new to MVC and ASP.NET so pretty confusing.
So you can do that in your controller.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,DisplayName,Date,Amount,Comment")] Charity charity)
{
if (ModelState.IsValid)
{
if(!string.IsNullOrEmpty(charity.Comment)
{
var comment = charity.Comment.ToLower().Replace("hot","###").Replace("cold","###");
charity.Comment = comment;
}
db.Donations.Add(charity);
db.SaveChanges();
return RedirectToAction("Additionalinfo", "Charities");
}
return View(charity);
}
I want to pack my data in form with foreign key and send that to database.I collect data from database with controller and show in my view and when I complete the form can not send that to database and see the exception
my controller code is
public ActionResult Register()
{
testContext test = new testContext();
List<SelectListItem> listselecteditem = new List<SelectListItem>();
foreach (Gender item in test.genders)
{
SelectListItem selectlist = new SelectListItem()
{
Text = item.GenderType,
Value = item.GenderID.ToString(),
};
listselecteditem.Add(selectlist);
}
ViewBag.Datalist = new SelectList(listselecteditem, "Value", "Text");
return View();
}
this controller get data from database and send to dropdownlist
and this controller save my data in database
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Person p)
{
using (testContext test=new testContext())
{
if (ModelState.IsValid)
{
try
{
test.persons.Add(p);
test.SaveChanges();
ViewBag.Message="Success";
}
catch (Exception ec)
{
ViewBag.Message = ec.Message;
}
}
}
return View(p);
}
this is my view
#model testmvc.Models.Person
<div class="container">
<div class="row">
<div class="pull-right col-sm-offset-3 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading ">
<p>register</p>
</div>
<div class="panel-body">
#using (Html.BeginForm("Register", "RegisterLogin", FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.ValidationSummary(true)
<fieldset>
#Html.AntiForgeryToken()
#if (ViewBag.Messsage != null)
{
<div class="alert alert-success">
<p>#ViewBag.Message</p>
</div>
}
<div class="form-group">
#Html.TextBoxFor(model => model.Fullname, new { #class = "form-control", #placeholder = "Full name" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Username, new { #class = "form-control input-sm", #id = "last_name", #placeholder = "Username" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.EmailAddress, new { #class = "form-control input-sm", #id = "email", #placeholder = "Email address" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Password, new { #class = "form-control input-sm floatlabel", #id = "first_name", #placeholder = "Password" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Comfirmpassword, new { #class = "form-control input-sm", #id = "last_name", #placeholder = "confirmpassword" })
</div>
<div class="form-group">
#*<select>
#foreach (var item in ViewBag.DataList)
{
<option>#item.Text</option>
}
</select>*#
#Html.DropDownList("Datalist",String.Empty)
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Birthday, new { #class = "form-control input-sm", #id = "password_confirmation", #placeholder = "Birthday yyyy/dd/mm" })
</div>
<div>
<input type="submit" value="Register" class="btn btn-primary">
</div>
</fieldset>
}
</div>
</div>
</div>
</div>
</div>
and my model code
public partial class Person
{
[Key]
public int personID { get; set; }
[Required]
public String Fullname { get; set; }
[Required]
public String Username { get; set; }
[Required]
public String Password { get; set; }
[Required]
[NotMapped]
public String Comfirmpassword { get; set; }
[Required]
public String EmailAddress { get; set; }
[DataType(DataType.DateTime)]
[Required]
public DateTime Birthday { get; set; }
public int GenderID { get; set; }
[ForeignKey("GenderID")]
public virtual Gender Gender { get; set; }
}
[Table("Gender")]
public partial class Gender
{
[Key]
public int GenderID { get; set; }
[Required]
public String GenderType { get; set; }
public virtual ICollection<Person> Persons { get; set; }
}
this exception said there is not any viewdata key with "Datalist". how can I solve that and what is my code problem
The reason you are getting this exception is because inside [HttpPost] action you didn't populate the ViewBag.Datalist property, the way you did in your Get action. Since you redisplay the same view and this view requires this information in order to properly render the dropdown, you will need to populate it. To avoid repetition you could place this logic in a separate method:
private SelectList GetGenders()
{
using (testContext test = new testContext())
{
List<SelectListItem> listselecteditem = new List<SelectListItem>();
foreach (Gender item in test.genders)
{
SelectListItem selectlist = new SelectListItem()
{
Text = item.GenderType,
Value = item.GenderID.ToString(),
};
listselecteditem.Add(selectlist);
}
return new SelectList(listselecteditem, "Value", "Text");
}
}
which you are going to call in your 2 actions:
public ActionResult Register()
{
ViewBag.Datalist = GetGenders();
return View();
}
and:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Person p)
{
using (testContext test = new testContext())
{
if (ModelState.IsValid)
{
try
{
test.persons.Add(p);
test.SaveChanges();
ViewBag.Message = "Success";
}
catch (Exception ec)
{
ViewBag.Message = ec.Message;
}
}
}
ViewBag.Datalist = GetGenders();
return View(p);
}
I can upload image. But I´ve made it without saving path to database. How can I do this?
I removed a few functions on a view that the code was shorter. I hope that everything is understood.
Here what i got:
MODEL:
public class Ogloszenie
{
[Key, ForeignKey("Pojazd")]
public int PojazdOgloszenieId { get; set; }
public RodzajPaliwa RodzajPaliwa { get; set; }
public int RokProdukcji { get; set; }
public int MocSilnika { get; set; }
public int Przebieg { get; set; }
public DateTime DataPrzegladu { get; set; }
public DateTime DataUbezpieczenia { get; set; }
public string OpisPojazdu { get; set; }
//path
public string Zdjecie { get; set; }
//path
public virtual Pojazd Pojazd { get; set; }
}
CONTROLLER:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PojazdOgloszenieId,RodzajPaliwa,RokProdukcji,MocSilnika,Przebieg,DataPrzegladu,DataUbezpieczenia,OpisPojazdu,Zdjecie")] Ogloszenie ogloszenie, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Zdjecia/"), fileName);
file.SaveAs(path);
//*********************?????????? Something like this?
Zdjecie = Url.Content("~/Zdjecia/" + file);
}
db.Ogloszenia.Add(ogloszenie);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.PojazdOgloszenieId = new SelectList(db.Pojazdy, "ID", "Marka", ogloszenie.PojazdOgloszenieId);
return View(ogloszenie);
}
VIEW:
#model AutoMonit.Models.Ogloszenie
<h2>Utwórz ogłoszenie</h2>
#using (Html.BeginForm("Create", "Ogloszenie", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.PojazdOgloszenieId, "PojazdOgloszenieId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.PojazdOgloszenieId, null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.PojazdOgloszenieId, "", new { #class = "text-danger" })
</div>
</div>
***************
.
.
.
***************
//FILE UPLOADING
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Utwórz" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Wróć", "Index")
</div>
Ok i made it (Thanks codeRecap for inspiration ;) )
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PojazdOgloszenieId,RodzajPaliwa,RokProdukcji,MocSilnika,Przebieg,DataPrzegladu,DataUbezpieczenia,OpisPojazdu")] Ogloszenie ogloszenie, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Zdjecia/"), fileName);
file.SaveAs(path);
ogloszenie.Zdjecie = Url.Content("~/Zdjecia/" + fileName);
}
db.Ogloszenia.Add(ogloszenie);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.PojazdOgloszenieId = new SelectList(db.Pojazdy, "ID", "Marka", ogloszenie.PojazdOgloszenieId);
return View(ogloszenie);
}
I have two classes where one is a parent class for the other. The basic CRUD functions was created in the controller. In the design of my table I have the parent id in my child class as the foreign key. In the view for Create function of the child, I am asked to enter the parent ID. I have changed the Create to accept the ID of the parent. But when I remove the code for selecting the parent id in the view I get exception in my Create. Is there a way I can set the parent ID in both my create functions(Over loaded functions).
public ActionResult Create(int? id)
{
ViewBag.LsystemID = new SelectList(db.Lsystem, "LsystemID", "LsystemName",id);
ViewBag.TCID = new SelectList(db.TC, "TCID", "TCName");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OptionID,OptionName,TCID,LsystemID")] Option option)
{
if (ModelState.IsValid)
{
db.Option.Add(option);
db.SaveChanges();
return RedirectToAction("Index");
}
// ViewBag.LsystemID = new SelectList(db.Lsystem, "LsystemID", "LsystemName", op);
ViewBag.TCID = new SelectList(db.TC, "TCID", "TCName", option.TCID);
return View(option);
}
View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.OptionName, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.OptionName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OptionName, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.TCID, "TCID", htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownList("TCID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TCID, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.LsystemID, "LsystemID", htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownList("LsystemID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LsystemID, "", new { #class = "text-danger" })
<input type="submit" value="Create" class="btn btn-default" />
}
How can I pass the value LsystemID without being shown in the View?
EDIT 1 : Adding Model class
public class Lsystem
{
public int LsystemID { get; set; }
public string LsystemName { get; set; }
public virtual ICollection<Option> Options { get; set; }
// public int OptionId { get; set; }
}
public class Option
{
public int OptionID { get; set; }
public string OptionName { get; set; }
public int TCID { get; set; }
public virtual TC tc { get; set; }
public virtual Lsystem Lsystem { get; set; }
public int LsystemID { get; set; }
public virtual ICollection<OptionValue> OptionValues { get; set; }
}
Start by creating a view model representing what you need in the view (add validation and display attributes as required
public class OptionVM
{
public int Lsystem { get; set; }
public string Name { get; set; }
public int TC { get; set; }
public SelectList TCList { get; set; }
}
and in the controller
public ActionResult Create(int? id)
{
OptionVM model = new OptionVM
{
Lsystem = id // set the parent
};
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(OptionVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
Option option = new Option
{
OptionName = model.Name,
TCID = model.TC,
LsystemID= model.Lsystem
};
db.Option.Add(option);
db.SaveChanges();
return RedirectToAction("Index");
}
private void ConfigureViewModel(OptionVM model)
{
model.TCList = new SelectList(db.TC, "TCID", "TCName");
}
and in the view
#model OptionVM
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Lsystem)
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMesageFor(m => m.Name)
#Html.LabelFor(m => m.TC)
#Html.DropDownListFor(m => m.TC, Model.TCList, "Please select")
#Html.ValidationMesageFor(m => m.TC)
<input type="submit" ... />
}