I have a form where a Chat is registered in the database, everything works fine, the problem is the ViewBag, since this takes the message to Javascript in the view so that it can place a validation. When the user registers, a success message should appear, but by the ViewBag it appears as an error, in the database if the user's data is displayed, so the only problem would be the ViewBag.
Also, when I re-run again, the modal with the message success appears just fine.
Controller
//Charlas
public ActionResult CrearCharla()
{
List<ClsSede> listaSede = new List<ClsSede>();
ClsSede Sede1 = new ClsSede();
Sede1.sede_Text = "LIMA - SAN BORJA";
Sede1.sede_Value = "LIMA - SAN BORJA";
ClsSede Sede2 = new ClsSede();
Sede2.sede_Text = "LIMA - LOS OLIVOS";
Sede2.sede_Value = "LIMA - LOS OLIVOS";
ClsSede Sede3 = new ClsSede();
Sede3.sede_Text = "LIMA - CHORRILLOS";
Sede3.sede_Value = "LIMA - CHORRILLOS";
listaSede.Add(Sede1);
listaSede.Add(Sede2);
listaSede.Add(Sede3);
ViewBag.Sedes = new SelectList(listaSede, "sede_Text", "sede_Value");
return View(new ClsCharla());
}
[HttpPost]
public ActionResult CrearCharla(ClsCharla charla)
{
List<ClsSede> listaSede = new List<ClsSede>();
ClsSede Sede1 = new ClsSede();
Sede1.sede_Text = "LIMA - SAN BORJA";
Sede1.sede_Value = "LIMA - SAN BORJA";
ClsSede Sede2 = new ClsSede();
Sede2.sede_Text = "LIMA - LOS OLIVOS";
Sede2.sede_Value = "LIMA - LOS OLIVOS";
ClsSede Sede3 = new ClsSede();
Sede3.sede_Text = "LIMA - CHORRILLOS";
Sede3.sede_Value = "LIMA - CHORRILLOS";
listaSede.Add(Sede1);
listaSede.Add(Sede2);
listaSede.Add(Sede3);
ViewBag.Sedes = new SelectList(listaSede, "sede_Text", "sede_Value", charla.sede_Charla);
//-----
string message = "";
try
{
ClsConexion con = new ClsConexion();
var Cnx = con.Conexion();
OracleCommand cmd = new OracleCommand("SIMEXA_SP_REGISTER_CHAT", Cnx);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("param_titulo", OracleDbType.Varchar2)).Value = charla.titulo_Charla.Trim();
cmd.Parameters.Add(new OracleParameter("param_descrip", OracleDbType.Varchar2)).Value = charla.descrip_Charla.Trim();
cmd.Parameters.Add(new OracleParameter("param_fecha", OracleDbType.Varchar2)).Value = charla.fecha_Charla;
cmd.Parameters.Add(new OracleParameter("param_hora", OracleDbType.Varchar2)).Value = charla.hora_Charla;
cmd.Parameters.Add(new OracleParameter("param_lugar", OracleDbType.Varchar2)).Value = charla.lugar_Charla.Trim();
cmd.Parameters.Add(new OracleParameter("param_sede", OracleDbType.Varchar2)).Value = charla.sede_Charla;
cmd.Parameters.Add(new OracleParameter("param_requisito", OracleDbType.Varchar2)).Value = charla.requisito_Charla.Trim();
Cnx.Open();
OracleTransaction tx = Cnx.BeginTransaction();
cmd.ExecuteNonQuery();
tx.Commit();
Cnx.Close();
cmd.Dispose();
Cnx.Dispose();
message = "success";
}
catch
{
message = "error";
}
finally
{
ViewBag.message = message;
}
return RedirectToAction("MostraCharlas");
}
View
#model wsCharlas.Models.ClsCharla
#{
ViewBag.Title = "Create a Chat";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create a Chat:</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h4>Here you can place all the respective data of the chat you want to create.</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<!-- <div class="form-horizontal"> -->
<div class="form-group">
#Html.HiddenFor(model => model.ID_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.HiddenFor(model => model.ID_Charla, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ID_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.titulo_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.titulo_Charla, new { htmlAttributes = new { #class = "form-control", maxlength = "40" } })
#Html.ValidationMessageFor(model => model.titulo_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.descrip_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.TextAreaFor(model => model.descrip_Charla, new { #id = "textArea", #class = "form-control", maxlength = "530" })
#Html.ValidationMessageFor(model => model.descrip_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.fecha_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.fecha_Charla, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.fecha_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.hora_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.hora_Charla, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.hora_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.lugar_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.lugar_Charla, new { htmlAttributes = new { #class = "form-control", maxlength = "100" } })
#Html.ValidationMessageFor(model => model.lugar_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.sede_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.DropDownListFor(model => model.sede_Charla, (SelectList)ViewBag.Sedes, "Select a Headquarters", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.sede_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.requisito_Charla, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.requisito_Charla, new { htmlAttributes = new { #class = "form-control", maxlength = "100" } })
#Html.ValidationMessageFor(model => model.requisito_Charla, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2">
<input type="submit" value="Create a Chat" id="id_charla" class="btn btn-success" />
</div>
</div>
<!--</div> -->
}
<div>
#Html.ActionLink("Return", "MostraCharlas", null, new { #class = "btn btn-primary" })
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
<style>
#textArea{
min-height: 62px;
max-height: 135px;
}
</style>
<script>
var msg = '#ViewBag.message'
$("#id_charla").on("click", function () {
if (msg == 'success') {
Swal.fire(
msg,
'A new chat was added!',
'success'
)
} else {
Swal.fire(
msg,
'Could not register your new chat, be sure to complete the entire form, if the problem continues to communicate with the computer area!',
'error'
)
}
});
</script>
To answer your question, I will start by saying that getting null for the ViewBag in your case is actually correct, because you used RedirectToAction which will nullify all ViewBag data
The lifespan of a ViewBag is the current request, which means that once you attempt to leave the current request, it becomes null. So you need to use TempData in your own case.
TempData is a data stored just the way sessions are stored. It's lifespan last between two request. It helps the transfer of data from one controller to another or from one action to another. You use TempData in a bit different way from the way View data or ViewBag is used.
So I will give two options for you.
First
Use TempData and ViewBag
In the Post action change the finally line to
finally
{
TempData["message"] = message;
}
Then in the Get action you are redirecting to, because you used RedirectToAction, get the TempData and pass it to view bag
var message = TempData ["message"];
If(message != null)
ViewBag.message = message;
Note the if statement is needed to handle initial get requests, that is not setting the value of the ViewBag when the TempData is not set
Second
Use only TempData
finally
{
TempData["message"] = message;
}
Whichever you decide to use, is accessed the same way you assigned it,
TempData["message"] //for TempData
ViewBag.message //for ViewBag
Related
I'm new to MVC and still figuring out how everything works. Currently, I am trying to call a method that is in my controller from my view but I'm not sure the best way to go about this. Here is my SalesOrdersController method that I want to run.
public ActionResult revertToPending(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
SalesOrder salesOrder = db.SalesOrders.Find(id);
if (salesOrder == null)
{
return HttpNotFound();
}
ViewBag.statusList = new List<Object>
{
new {value = SOStatus.Pending, text = "Pending" },
new {value = SOStatus.Released, text = "Released" },
new {value = SOStatus.Released, text = "Shipped" },
new {value = SOStatus.BackOrdered, text = "Back Ordered" },
new {value = SOStatus.Cancelled, text = "Cancelled" },
};
return View(salesOrder);
}
Here is my view
<div class="form-group">
#Html.LabelFor(model => model.SalesOrderStatus, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SalesOrderStatus, new SelectList(ViewBag.statusList, "value", "text"), new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.SalesOrderStatus, "", new { #class = "text-danger" })
#Html.ActionLink("Revert to Pending", "revertToPending", "SalesOrder")
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BillingStatus, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EnumDropDownListFor(model => model.BillingStatus, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BillingStatus, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Details, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.Details, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Details, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn" />
</div>
</div>
And I want that to run when the user presses a button from the view.
So something like this
#Html.ActionLink("Revert to Pending", "revertToPending", "SalesOrder" )
I know that I'm doing it wrong as I don't want it to lead to the revertToPending View as it doesn't exist. But I want that controller method to run when the link is pressed.
Thanks
What I'm wanting is for a person to register (using existing register page) then get directed to a form where their AspNetUsers.Id = UserId (on my CreateProfile page). CreateProfile is the page you are directed to when you have successfully registered. As you can see in the image in the address bar you can see the user id but it won't appear in the input box.
AccountController
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// Registered user is given the applicant role by default
UserManager.AddToRole(user.Id, "Applicant");
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking here");
ViewBag.UserId = user.Id;
//return RedirectToAction("Index", "Home");
return RedirectToAction("CreateProfile", new { controller = "Admin", UserId = user.Id });
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
CreateProfile View
#model NAA.Data.Profile
#{
ViewBag.Title = "CreateProfile";
}
<h2>Create Profile</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Profile</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ApplicantName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ApplicantName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ApplicantName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ApplicantAddress, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ApplicantAddress, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ApplicantAddress, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserId, new { htmlAttributes = new { #class = "form-control", } })
#Html.ValidationMessageFor(model => model.UserId, "", 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>
</div>
}
<div>
#Html.ActionLink("Back to List", "GetProfile", new { controller = "Profile", action = "GetProfile" })
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Image of CreateProfile
Controller Action
you have two main problems:
In Register action you pass userId value using ViewBag and later use RedirectToAction. You cannot use ViewBag for this scenario, because value will loss. Check here
You don't assign UserId value on input box [CreateProfile view].
To solve it:
Capture UserId value in CreateProfile Get Action and later assign in ViewBag to pass value to View. Two forms:
a. Use MVC bind, set a variable:
// Get: Admin/CreateProfile
public ActionResult CreateProfile(string UserId) // <== here
{
ViewBag.UserId = UserId;
return View();
}
b. Use request object to get value.
// Get: Admin/CreateProfile
public ActionResult CreateProfile()
{
ViewBag.UserId = Request.Params["UserId"]; // <== here
return View();
}
Optional: you could save UserId value using Session Object in Register Action. Maybe I would like this because avoid before code. Check here.
Finally assign UserId value on input box in CreateProfile view using #Value:
new { htmlAttributes = new { #class = "form-control", #Value=
ViewBag.UserId }
I.E:
<div class="form-group">
#Html.LabelFor(model => model.UserId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserId, new { htmlAttributes = new { #class = "form-control", #Value= ViewBag.UserId } })
#Html.ValidationMessageFor(model => model.UserId, "", new { #class = "text-danger" })
</div>
</div>
This question already has answers here:
foreach returns only last item repeatedly in c sharp
(1 answer)
In a loop, is to create new object is so necessary?
(2 answers)
Closed 4 years ago.
I'm new to C# and I'm coding a web site in witch I need to insert multiple data in a row inside my database. some of the data will be set automatically and the others from form. here is my controller part:
public ActionResult chekout()
{
return View(new Commande());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult chekout([Bind(Include = "Id_commande,prenom,nom,Adresse,telephone,Email,produit,prix,cart")] Commande commande)
{
var panier = from Panier in db.Paniers
select Panier;
var userEmail = this.User.Identity.Name;
panier = panier.Where(x => x.user.Contains(userEmail));
Panier[] pa = panier.ToArray();
List<Commande> list = new List<Commande>();
for (int i = 0; i < pa.Length; i++)
{
commande.Id_commande = db.Commandes.Max(I => I.Id_commande) + 1;
commande.produit = pa[i].Quantite + " X " + pa[i].nom_produit;
commande.prix = int.Parse(pa[i].prix) * pa[i].Quantite;
commande.Email = userEmail;
list.Add(commande);
}
db.Commandes.AddRange(list);
db.SaveChanges();
return RedirectToAction("order_complete", "Home");
}
and this is my view part:
#using(Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.prenom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.prenom, new { htmlAttributes = new { #class = "form-control", required = "required", title = "veuillez remplir ce champ" } })
#Html.ValidationMessageFor(model => model.prenom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.nom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.nom, new { htmlAttributes = new { #class = "form-control", required = "required", title = "veuillez remplir ce champ" } })
#Html.ValidationMessageFor(model => model.nom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Adresse, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Adresse, new { htmlAttributes = new { #class = "form-control", required = "required", title = "veuillez remplir ce champ" } })
#Html.ValidationMessageFor(model => model.Adresse, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.telephone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.telephone, new { htmlAttributes = new { #class = "form-control", required = "required", title = "veuillez remplir ce champ" } })
#Html.ValidationMessageFor(model => model.telephone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.cart, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.cart, new { htmlAttributes = new { #class = "form-control", required = "required", title = "veuillez remplir ce champ" } })
#Html.ValidationMessageFor(model => model.cart, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type = "submit" value="Commander" class="btn btn-primary" />
</div>
</div>
}
I do not get error but I don't know why but it just adds the last row
so if anyone can help me I would be grateful.
You are adding the same commande object repeatedly in the loop, you need to instantiate new object commande in every iteration. You need to add the first line in loop below, please do change the variable name "commande" if a same name exist at class level.
for (int i = 0; i < pa.Length; i++)
{
Commande commande = new Commande ();
commande.Id_commande = db.Commandes.Max(I => I.Id_commande) + 1;
commande.produit = pa[i].Quantite + " X " + pa[i].nom_produit;
commande.prix = int.Parse(pa[i].prix) * pa[i].Quantite;
commande.Email = userEmail;
list.Add(commande);
}
I know that the question was asked and answered many times, but unfortunately no one of the answers helped me.
I have tree POCO models, which are Pharmacy, Address and Company gathered together into a ViewModel PharmacyVM:
public class PharmacyVM
{
public Pharmacy pharmacyProp { get; set; }
public Address addressProp { get; set; }
public Company companyProp { get; set; }
public int CityId { get; set; }
public PharmacyVM()
{
pharmacyProp = new Pharmacy();
addressProp = new Address();
companyProp = new Company();
}
}
Don't laugh at the properties names; at the start, they had been normal (Address, Company and Pharmacy) I changed them according to one of the lots of answers in here, but... it didn't help :(
In the Get action of the Create method I'm trying to manually create the PharmacyVM object and pass it to the view:
public ActionResult Create()
{
ViewBag.CityId = new SelectList(db.Cities, "Id", "Name");
ViewBag.CompanyId = new SelectList(db.Companies, "Id", "Name");
ViewBag.AddressId = new SelectList(db.Addresses, "Id", "Name");
ViewBag.CityId = new SelectList(db.Cities, "Id", "Name");
ViewBag.RegionId = new SelectList(db.Regions, "Id", "Name");
ViewBag.DistrictId = new SelectList(db.Districts, "Id", "Name");
ViewBag.MicrodistrictId = new SelectList(db.Microdistricts, "Id", "Name");
ViewBag.StreetId = new SelectList(db.Streets, "Id", "Name");
ViewBag.VillageId = new SelectList(db.Villages, "Id", "Name");
var pharmacyVM = new PharmacyVM();
return View(pharmacyVM);
}
There is a standard Razor code in the view:
#model MEDONET.Models.PharmacyVM
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "Pharmacies", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>pharmacyProp</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.companyProp, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CompanyId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.companyProp.Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.pharmacyProp.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.pharmacyProp.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.pharmacyProp.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.City, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CityId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CityId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CityId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CityId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CityId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.Village, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("VillageId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.addressProp.VillageId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.District, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("DistrictId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.addressProp.DistrictId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.HiddenFor(model => model.addressProp.RegionId)
#Html.LabelFor(model => model.addressProp.Region, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("RegionId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.addressProp.RegionId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.Microdistrict, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("MicrodistrictId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.addressProp.MicrodistrictId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.Building, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.addressProp.Building, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.addressProp.Building, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.addressProp.Street, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("MicrodistrictId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.addressProp.MicrodistrictId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.pharmacyProp.IsGov, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.pharmacyProp.IsGov)
#Html.ValidationMessageFor(model => model.pharmacyProp.IsGov, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.companyProp, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("companyId", null, "", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.pharmacyProp.CompanyId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.pharmacyProp.LargeImage, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="LargeImageFile" required />
</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>
</div>
}
<div> #Html.ActionLink("Back to List", "Index")</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And then in the Post action of the Create method, I'm trying to create b and c variables:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PharmacyVM model, HttpPostedFileBase LargeImageFile)
{
if (ModelState.IsValid)
{
string LargeImageFileName = Path.GetFileNameWithoutExtension(LargeImageFile.FileName);
string LargeImageExtansion = Path.GetExtension(LargeImageFile.FileName);
LargeImageFileName = LargeImageFileName + DateTime.Now.ToString("yymmssfff") + LargeImageExtansion;
LargeImageFileName = Path.Combine(Server.MapPath("~/Images/Pharmacy/Banners/"), LargeImageFileName);
int b = model.CityId;
int c = model.addressProp.RegionId.Value;
//Address address = new Address()
//{
// Id = 12,//db.Addresses.AsEnumerable().Last().Id + 1,
// RegionId = PharmacyVM.Address.RegionId,
// DistrictId = PharmacyVM.Address.DistrictId,
// CityId = PharmacyVM.Address.CityId,
// MicrodistrictId = PharmacyVM.Address.MicrodistrictId,
// StreetId = PharmacyVM.Address.StreetId,
// VillageId = PharmacyVM.Address.VillageId,
// Building = PharmacyVM.Address.Building,
// Cab = PharmacyVM.Address.Cab
//};
//Address address = new Address
//{
// Id = 12,//db.Addresses.AsEnumerable().Last().Id + 1,
// RegionId = 1,
// DistrictId = 1,
// CityId = 1,
// MicrodistrictId = 1,
// StreetId = 1,
// VillageId = 1,
// Building = "1",
// Cab = "1"
//};
//db.Addresses.Add(address);
db.SaveChanges();
var pharmacy = new Pharmacy
{
Name = model.pharmacyProp.Name,
//AddressId = address.Id,
IsGov = model.pharmacyProp.IsGov,
CompanyId = model.pharmacyProp.CompanyId,
LargeImage = "~/Images/Pharmacy/Banners/" + LargeImageFileName
};
LargeImageFile.SaveAs(LargeImageFileName);
db.Pharmacies.Add(pharmacy);
db.SaveChanges();
ModelState.Clear();
return RedirectToAction("Index");
}
}
Unlike first variable b, the second one c is gonna be null because the addressProp property is null.
So why is it so strange? How can I use ViewModel without duplicating original model's fields?
why are you use
int b= model.addressProp.RegionId.Value
instead of
int b=model.addressProp.RegionId
Even for your good cording the best and good way is remove all View bag and
Add all View bag properties to PharmacyVM Class
Dont use two properties for view binding
Example
public class PharmacyVM
{
public Pharmacy pharmacyProp { get; set; }
public Address addressProp { get; set; }
public Company companyProp { get; set; }
public int CityId { get; set; }
public SelectList CityIdList { get; set; }
public PharmacyVM()
{
pharmacyProp = new Pharmacy();
addressProp = new Address();
companyProp = new Company();
CityIdList =new SelectList(db.Cities, "Id", "Name");
}
}
public ActionResult Create()
{
var pharmacyVM = new PharmacyVM();
return View(pharmacyVM);
}
#model PharmacyVM
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.CityId )
<div class="editor-label">
#Html.LabelFor(m => m.Name)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
<button type="submit">Create</button>
}
[HttpPost]
public ActionResult Create(PharmacyVM model)
{
int c = model.addressProp
return View(viewModel);
}
More Information
We've got a page which currently contains a four or five partial views, but is something that could grow. At the moment, there's two POST actions, for two entirely different database functions.
If we try doing the create function on another, the redirect then results in an "Object reference not set to an instance of an object." error, which is then relating to the other POST partial view.
Is there a way to stop this? Essentially, it seems to me that the post for one partial view is trying to interact with the other. Any ideas?
Thanks
Bulletins Controller for Creating:
[HttpPost]
public ActionResult CreateMain(BulletinsViewModel viewModel)
{
if (ModelState.IsValid)
{
BulletinsContext.tblBulletins.Add(new tblBulletin
{
ID = viewModel.BulletinID,
BulletinDisplayDate = viewModel.BulletinDisplayDate,
BulletinFilename = viewModel.MainBulletinName,
IsSixthForm = viewModel.IsSixthForm
});
//For loop to delete bulletins
//If bulletin folder has more than 10 files in
//Delete the oldest file, itererate till only 10 remain
{
DirectoryInfo dir = new DirectoryInfo(#"D:\Inetpub\WWWroot\intranet\Dashboard\Dashboard\Files\Bulletins");
List<FileInfo> filePaths = dir.GetFiles().OrderByDescending(p => p.CreationTime).ToList();
for (int index = filePaths.Count() - 1; index > 9; index--)
{
var fileNames = filePaths[index].Name;
//Delete from directory
filePaths[index].Delete();
//Remove from collection to restart the loop
filePaths.RemoveAt(index);
}
}
//Save changes to database
BulletinsContext.SaveChanges();
//Return to main bulletins index page
return RedirectToAction("~/Home/Index");
}
return View(viewModel);
}
Bulletins Create View:
#model Dashboard.Viewmodels.BulletinsViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.BulletinDisplayDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BulletinDisplayDate, new { htmlAttributes = new { #class = "form-control", #id = "datepicker-basic", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.BulletinDisplayDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MainBulletinName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="input-group">
#Html.EditorFor(model => model.MainBulletinName, new { htmlAttributes = new { #class = "form-control", #Value = "Select File...", #readonly="readonly" } })
<span class="input-group-addon" href="javascript:;" onclick="moxman.browse({ fields: 'MainBulletinName', extensions: 'pdf', path: 'D:/Inetpub/WWWroot/intranet/Dashboard/Dashboard/Files/Bulletins' });" style="cursor: pointer;"><i class="fa fa-upload"></i></span>
#Html.ValidationMessageFor(model => model.MainBulletinName, "", new { #class = "text-danger" })
</div>
</div>
</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>
}
<script type="text/javascript" src="~/Scripts/tinymce/plugins/moxiemanager/js/moxman.loader.min.js"></script>
Printer Credits Create Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PrinterCredits(PrinterCreditsViewModel viewModel)
{
if (ModelState.IsValid)
{
//Send the email if credits are added..
//Create a bunch of variables for the email
//Create the email body etc
var fromAddress = "";
string toName = Request.Form["Username"].ToUpper();
string AmountOfCredits = Request.Form["AmountAdded"];
string Plural = "";
string Title = "";
string AddedByWho = User.Identity.Name.Split('\\')[1];
System.DateTime AddedWhen = DateTime.Now;
if (AmountOfCredits == "1")
{
Plural = " printer credit has ";
Title = "Printer Credit Added!";
}
else
{
Plural = " printer credits have ";
Title = "Printer Credits Added!";
}
var toEmail = toName + "";
var subject = AmountOfCredits + Plural + "been added to your account, " + toName;
string body = "";
//Create an SMTP client for sending an email
var smtp = new SmtpClient
{
Host = "",
Port = 25,
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = true,
};
//Populate the SMTP client and encode the body for the HTML
using (var message = new MailMessage(fromAddress, toEmail)
{
Subject = subject,
Body = body,
IsBodyHtml = true,
BodyEncoding = System.Text.Encoding.UTF8
})
//Try to send the email. If sent, insert data.
//Redirect back to original page
//Take current printer credit from and update with fund + cost
try
{
//Link the viewmodel and the database together
PartialViewContext.tblPrinterCredits.Add(new tblPrinterCredit
{
Username = viewModel.Username,
AmountAdded = viewModel.AmountAdded,
AddedBy = AddedByWho,
AddedWhen = viewModel.AddedWhen,
Money = viewModel.AmountAdded * 0.02
});
Nullable<double> cost = viewModel.AmountAdded * 0.02;
//Update the printer credit fund and insert into tblOption
tblOption fund = (
from n in PartialViewContext.tblOptions
where n.ID == 1
select n).First();
fund.PrinterCreditFund = fund.PrinterCreditFund + cost;
PartialViewContext.SaveChanges();
message.CC.Add("");
smtp.Send(message);
Response.Redirect("~/Home/Index");
}
//If it fails, go chicken oriental (only a redirect, will eventually become a crazy message)
catch
{
smtp.Send(message);
Response.Redirect("~/Home/Index");
}
}
return View(viewModel);
Printer Credits View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="panel">
<div class="panel-heading">
<span class="panel-icon">
<i class="fa fa-print"></i>
</span>
Add Printer Credits - #Costings
</div>
<div class="panel-body">
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<label class="control-label col-md-3">User:</label>
<div class="col-xs-8">
#Html.EditorFor(model => model.Username, new { htmlAttributes = new { #class = "form-control", #id = "Username", #name = "Username", #maxlength = "6" } })
#Html.ValidationMessageFor(model => model.Username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Amount:</label>
<div class="col-xs-8">
#Html.EditorFor(model => model.AmountAdded, new { htmlAttributes = new { #class = "form-control", #id = "AmountAdded", #onkeyup = "Update()", #Value = 0 } })
#Html.ValidationMessageFor(model => model.AmountAdded, "", new { #class = "text-danger", #type="number" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Cost:</label>
<div class="col-xs-8">
#Html.EditorFor(model => model.TotalCost, new { htmlAttributes = new { #class = "form-control", #id = "TotalCost", #readonly = "readonly", #Value = "0" } })
#Html.ValidationMessageFor(model => model.TotalCost, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-1 col-md-10">
<input type="submit" value="Add Printer Credits" class="btn btn-primary btn-gradient dark btn-block" />
#Html.EditorFor(model => model.AddedBy, new { htmlAttributes = new { #class = "form-control", #Value = User.Identity.Name.Split('\\')[1], #Style = "display: none;" } })
#Html.ValidationMessageFor(model => model.AddedBy, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
}
<script type="text/javascript">
$(document).ready(
function () {
Update();
$('#AmountAdded, #TotalCost')
.keyup(function () {
Update();
})
}
);
function Update() {
var cost = 2
var one = $('#AmountAdded'),
two = $('#TotalCost');
two.val(parseInt(one.val()) * cost / 100);
}
</script>
<script type="text/javascript">
document.getElementById('Username').focus()
</script>
Just figured out that I need to tell the form which action and controller to use, despite the fact two different controllers are running the views. But anyway, an example is:
#using (Html.BeginForm("CreateMain", "Bulletins", FormMethod.Post, new { }))