Model is set to null when i submit it - asp.net

I'm trying to update records inside a Table, but when i submit the record the model it set to Null.
What i want to happen is to have a multi table single view page where i can edit my ParentModel
and the records inside my model1s
i have a submit button for Parentmodel which works
and a submit button for each recods in Model1s
but everytime i submit any model1s records the debug says that my model is Null
i'm quite new with ASP.Net and already search alot from this forum,
i hope you can help me out
Cheers
View Model
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace WebApplication1.Models
{
public class CombineModel
{
public ParentModel ParentModel { get; set; }
public IEnumerable<Model1> Model1s { get; set; }
}
}
Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class CombineModelController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CombineModel CombineModel = new CombineModel();
CombineModel.ParentModel = db.ParentModel.Find(id);
CombineModel.Model1s = db.Model1.Where(x => x.ParentId.Equals(id));
if (CombineModel == null)
{
return HttpNotFound();
}
return View(CombineModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(CombineModel model)
{
if (ModelState.IsValid)
{
db.Entry(model.ParentModel).State = EntityState.Modified;
db.SaveChanges();
}
CombineModel CombineModel = new CombineModel();
CombineModel.ParentModel = db.ParentModel.Find(model.ParentModel.ParentId);
CombineModel.Model1s = db.Model1.Where(x => x.ParentId.Equals(model.ParentModel.ParentId));
if (CombineModel == null)
{
return HttpNotFound();
}
return View(CombineModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditChild([Bind(Prefix = "Model1")] Model1 model)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", "CombineModel", new { id = model.ParentId });
}
}
}
View
#model WebApplication1.Models.CombineModel
#{
ViewBag.Title = "Details";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Combine Model</h4>
<hr />
#Html.HiddenFor(model => model.ParentModel.ParentId)
<div class="form-group">
#Html.LabelFor(model => model.ParentModel.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ParentModel.Name, new { htmlAttributes = new { #class = "form-control" } })
</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>
}
<table class="table">
<tr>
<th>
Name
</th>
</tr>
#foreach (var item in Model.Model1s)
{
<tr>
<td>
#using (Html.BeginForm("EditChild", "CombineModel", FormMethod.Post, new { }))
{
#Html.AntiForgeryToken()
#Html.EditorFor(modelItem => item.Id)
#Html.EditorFor(modelItem => item.ParentId)
#Html.EditorFor(modelItem => item.Name)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save-2" class="btn btn-default" />
</div>
</div>
}
</td>
</tr>
}
</table>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}

Related

asp.net MVC how to modify one column only

Hi I have this piece of code that works when updating data into db.
However i have 20 columns in my table. how can i make sure:
1) Only ACCOUNT_ID will be updated? (currently all 17 columns get overwritten into NULL after updating)
2) how to indicate in UI that only ACCOUNT_ID is editable? (eg greyed out)
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MovieApp.Models;
namespace MovieApp.Controllers
{
public class HomeController : Controller
{
private dtsdbEntities _db = new dtsdbEntities();
// GET: Home
public ActionResult Index()
{
return View(_db.IPR_CompanyGen_200200501.ToList());
}
// GET: Home/Edit/5
public ActionResult Edit(int id)
{
var CompanyToEdit = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(id.ToString())) select m);
return View(CompanyToEdit);
}
// GET: Home/Edit/5
[HttpPost]
public ActionResult Edit(IPR_CompanyGen_200200501 CompanyToEdit)
{
var OriginalCompany = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(CompanyToEdit.CompanyID.ToString())) select m.First());
_db.Entry(OriginalCompany).CurrentValues.SetValues(CompanyToEdit).First();
_db.SaveChanges();
return RedirectToAction("Index");
}
}
internal class MoviesDBEntities
{
}
}
Edit.cshtml
#model MovieApp.Models.IPR_CompanyGen_200200501
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>IPR_CompanyGen_200200501</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.CompanyID)
<div class="form-group">
#Html.LabelFor(model => model.CompanyName, htmlAttributes: new { #class = "control-label
col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { #class =
"form-control" } })
#Html.ValidationMessageFor(model => model.CompanyName, "", new { #class = "text-
danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ACCOUNT_ID, htmlAttributes: new { #class = "control-label
col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ACCOUNT_ID, new { htmlAttributes = new { #class =
"form-control" } })
#Html.ValidationMessageFor(model => model.ACCOUNT_ID, "", 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 btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Tried with Bind but still columns goes to NULL (take CompanyName , Address1 as example)
[HttpPost]
public ActionResult Edit([Bind(Include = "CompanyID,CompanyName,Address1,Address2,Address3,City,StateProvinceCode,PostalCode,CountryCode,Region,PhoneNumber,URL,PrimaryCompanyType, DominantCompanyStyle, DominantCompanyOrientation, Buy_side, Sell_side, Strategic, EqPortfolioTurnover, ReportedEquityAssets, Status, LastModifiedDate, ACCOUNT_ID, CRM_Comments")] IPR_CompanyGen_200200501 CompanyToEdit)
{
if (ModelState.IsValid) {
var OriginalCompany = (from m in _db.IPR_CompanyGen_200200501 where (m.CompanyID.Equals(CompanyToEdit.CompanyID.ToString())) select m).First();
OriginalCompany.CompanyName = CompanyToEdit.CompanyName;
OriginalCompany.Address1 = CompanyToEdit.Address1;
_db.Entry(OriginalCompany).CurrentValues.SetValues(CompanyToEdit);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
This is your problem with your code:
OriginalCompany.CompanyName = CompanyToEdit.CompanyName;
OriginalCompany.Address1 = CompanyToEdit.Address1;
_db.Entry(OriginalCompany).CurrentValues.SetValues(CompanyToEdit);
You get the originalCompany from db assing new values to it and finally you edit the object which came as parameter which have all other properties null.
Replace it with this:
_db.Entry(OriginalCompany).CurrentValues.SetValues(OriginalCompany);
On the values that should not be touched at all, in the view, on the class="form-control" add a disabled attribute. Like
class="form-control" disabled
Also to prevent the values from being set NULL, put a Bind() in the [HttpPost] part of the controller. Like so
[HttpPost]
public ActionResult Edit([Bind(Include ="Id,Account_Id,NextField,OtherField,etc.")] IPR_CompanyGen_200200501 CompanyToEdit)
Inside of the [Bind("")], just put the column names that exist in the model. In the controller have if(ModelState.IsValid)
public ActionResult Edit(int id)
{
var CompanyToEdit = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(id.ToString())) select m);
return View(CompanyToEdit);
}
// GET: Home/Edit/5
[HttpPost]
public ActionResult Edit([Bind(Include="Id,Company_Id,Account_Id,Other_Properties")] IPR_CompanyGen_200200501 CompanyToEdit)
{
if (ModelState.IsValid) {
var OriginalCompany = (from m in _db.IPR_CompanyGen_200200501 where
(m.CompanyID.Equals(CompanyToEdit.CompanyID.ToString())) select m.First());
OriginalCompany.CompanyName = CompanyToEdit.CompanyName;
OriginalCompany.Company_ID = CompanyToEdit.Company_ID;
OriginalCompany.WhatEverProperty = CompanyToEdit.WhatEverProperty;
OriginalCompany.Account_ID = CompanyToEdit.Account_ID;
//do this for every property and place a breakpoint to view every value
_db.Entry(OriginalCompany).CurrentValues.SetValues(CompanyToEdit).First();
_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}

Email Attachment ASP.Net MVC 5 not attaching

I don't receive any errors, and the message itself is received. The attachment isn't included.
I do not program for the website often. The company asked me to add this and this is far as I've come via other guides. Any information is appreciated!
Index.cshtml:
#using (Html.BeginForm())
{
//Captcha authentication
#Html.AntiForgeryToken()
//Form entry field validation
#Html.ValidationSummary(true)
<div class="row">
<div class="form-group col-lg-4">
#Html.LabelFor(model => model.Name, "Name")<br />
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="form-group col-lg-4">
#Html.LabelFor(model => model.Email, "Email Address")<br />
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="form-group col-lg-4">
#Html.LabelFor(model => model.Telephone, "Phone Number")<br />
#Html.EditorFor(model => model.Telephone)
#Html.ValidationMessageFor(model => model.Telephone)
</div>
<div class="clearfix"></div>
<div class="form-group col-lg-12">
#Html.LabelFor(model => model.Comment, "Message")<br />
#Html.TextAreaFor(model => model.Comment, new { #class = "text-boxMessage" })
#Html.ValidationMessageFor(model => model.Comment)
</div>
<div class="form-group col-lg-4">
<input type="file" name="fileUploader"/>
</div>
</div>
<div class="row">
<div class="g-recaptcha" data-sitekey="6Lcvzo0UAAAAAAdAu2zUmDIODBEDTsDvzmgANNdb"></div>
<div class="form-group col-lg-12">
<input class="btn btn-default" type="submit" value="Submit" />
</div>
</div>
}
The method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Mvc4ContactForm.Models
{
public class ContactModels
{
[Required(ErrorMessage="*Required")]
public string Name { get; set; }
[Required(ErrorMessage= "*Required")]
[RegularExpression(#"^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$", ErrorMessage = "Invalid email")]
public string Email { get; set; }
[Required(ErrorMessage = "*Required")]
public string Telephone { get; set; }
[Required(ErrorMessage= "*Required")]
public string Comment { get; set; }
public HttpPostedFileBase FileUploader { get; set; }
}
}
The controller:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using Mvc4ContactForm.Models;
namespace correinc.Controllers
{
public class ContactController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
//For captcha
[ValidateAntiForgeryToken]
public ActionResult Index(ContactModels c)
{
if (ModelState.IsValid)
{
//For captcha
CaptchaResponse response = ValidateCaptcha(Request["g-recaptcha-response"]);
if (response.Success && ModelState.IsValid)
{
//For data to smtp
try
{
MailMessage msg = new MailMessage();
SmtpClient client = new SmtpClient();
MailAddress from = new MailAddress(c.Email.ToString());
System.Text.StringBuilder sb = new System.Text.StringBuilder();
msg.IsBodyHtml = false;
client.Host = "smtp.gmail.com";
client.Port = 587;
client.EnableSsl = true;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new System.Net.NetworkCredential("a#b.com", "password");
msg.To.Add("b#b.com");
msg.From = from;
msg.Subject = "Website Contact Form";
sb.Append("Name: " + c.Name);
sb.Append(Environment.NewLine);
sb.Append("Email: " + c.Email);
sb.Append(Environment.NewLine);
sb.Append("Telephone: " + c.Telephone);
sb.Append(Environment.NewLine);
sb.Append("Comments: " + c.Comment);
//Fileuploader
if (c.FileUploader != null)
{
string fileName = Path.GetFileName(c.FileUploader.FileName);
msg.Attachments.Add(new Attachment(c.FileUploader.InputStream, fileName));
}
msg.IsBodyHtml = false;
msg.Body = sb.ToString();
client.Send(msg);
msg.Dispose();
return View("Success");
}
catch (Exception)
{
return View("Error");
}
}
//Captcha
else
{
return Content("Error From Google ReCaptcha : " + response.ErrorMessage[0].ToString());
}
}
return View();
}
//Captcha
public class CaptchaResponse
{
[JsonProperty("success")]
public bool Success
{
get;
set;
}
[JsonProperty("error-codes")]
public List<string> ErrorMessage
{
get;
set;
}
}
public static CaptchaResponse ValidateCaptcha(string response)
{
string secret = System.Web.Configuration.WebConfigurationManager.AppSettings["recaptchaPrivateKey"];
var client = new System.Net.WebClient();
var jsonResult = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, response));
return JsonConvert.DeserializeObject<CaptchaResponse>(jsonResult.ToString());
}
}
}
You have to set the enctype to the form property for the file uploads.
Please use the following
#using (Html.BeginForm("Index", "Contact", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
....
....
}
Please see the similar discussion in this SO thread.

all my textboxes return null what should I do?

I have a problem here with regards to elements on my pages returning null even though I have typed something in the textbox. What causes this? I want to make a simple CRUD app with a dashboard for final year.
Here is my view:
#model WebApplication1.Models.Category
#{
ViewBag.Title = "Create Category";
}
<h2>#ViewBag.Title</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class
="control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Name, new { htmlAttributes =
new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", 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", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Here is my controller action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name")] Category category)
{
if (ModelState.IsValid)
{
db.Categories.Add(category);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
I think you need to post to the correct ActionName. You use #using (Html.BeginForm()), which will post to the Index of a Controller. But you have Create. So point the form to that.
#using (Html.BeginForm("Create", "Home", FormMethod.Post))
Make sure that you have proper viewmodel properties setup first:
public class Category
{
public int ID { get; set; }
public string Name { get; set; }
}
Then point to action name and controller name which handles POST action in BeginForm helper:
#* assumed the controller name is 'CategoryController' *#
#using (Html.BeginForm("Create", "Category", FormMethod.Post))
{
// form contents
}
And finally change parameter name to avoid naming conflict in default model binder, also remove BindAttribute because the POST action has strongly-typed viewmodel class as parameter:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Category model)
{
if (ModelState.IsValid)
{
db.Categories.Add(model);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
Related issue:
POST action passing null ViewModel

ArgumentNullException on MVC5 DropdownListFor

I just started learning Asp.net MVC5 and I'm getting a ArgumentNullException on the following line.
#Html.DropDownListFor(m => m.Customer.MembershipTypeId, new SelectList(Model.MembershipTypes, "Id", "Name"), "", new { #class = "form-control" })
I'm following a tutorial and I have it the exact same so I'm not sure why it's throwing this error.
I looked over the models and table data and they are populated.
Let me know if any additional info is needed to figure out this issue.
New.cshtml
#model Vidly6.VIewModel.NewCustomerViewModel
#{
ViewBag.Title = "New";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>New Customer</h2>
#using (Html.BeginForm("Create", "Customers"))
{
<div class="form-group">
#Html.LabelFor(m => m.Customer.Name)
#Html.TextBoxFor(m => m.Customer.Name, new {#class = "form-control"})
</div>
<div class="form-group">
#Html.LabelFor(m => m.Customer.BirthDate)
#Html.TextBoxFor(m => m.Customer.BirthDate, new {#class = "form-control"})
</div>
<div class="checkbox">
<label>
#Html.CheckBoxFor(m=>m.Customer.IsSubscribedToNewsletter) Subscribed to Newsletter?
</label>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Customer.MembershipTypeId)
#Html.DropDownListFor(m => m.Customer.MembershipTypeId, new SelectList(Model.MembershipTypes, "Id", "Name"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Customer.MembershipTypeId)
</div>
}
NewCustomerViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Vidly6.Models;
namespace Vidly6.VIewModel
{
public class NewCustomerViewModel
{
public IEnumerable<MembershipTypes> MembershipTypes { get; set; }
public Customers Customer { get; set; }
}
}
CustomersController
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Vidly6.Models;
using Vidly6.VIewModel;
namespace Vidly6.Controllers
{
public class CustomersController : Controller
{
private ApplicationDbContext _context;
public CustomersController()
{
_context = new ApplicationDbContext();
// GET: Customers
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
}
public ActionResult New()
{
var membershipTypes = _context.MembershipTypes.ToList();
var viewModel = new NewCustomerViewModel();
return View(viewModel);
}
public ViewResult CustomerGoesHere()
{
var customers = _context.Customers.Include(c => c.MembershipTypes).ToList();
return View(customers);
}
public ActionResult Details(int id)
{
var customer = _context.Customers.SingleOrDefault(c => c.Id == id);
if (customer == null)
return HttpNotFound();
return View(customer);
}
}
}
MembershipTypes Table
public ActionResult New()
{
var membershipTypes = _context.MembershipTypes.ToList();
var viewModel = new NewCustomerViewModel();
return View(viewModel);
}
You don't actually use membershipTypes. You need to set the property on the viewModel otherwise it will be null.

asp.net mvc model didn't receive on form submit

I have written an asp.net mvc site that works fine on local.
But after publishing it, i have some problems with models sent from forms.
i think it determines my model state always not valid.
i don't receive any data!
[HttpGet]
public ActionResult LogIn()
{
return View();
}
[HttpPost]
public ActionResult LogIn(Models.LoginViewModel data)
{
if (!ModelState.IsValid)
{
return LogIn();
}
TAPortalEntities db = new TAPortalEntities();
UserAccount probableUser = db.UserAccounts.FirstOrDefault(p => p.UserName == data.UserName && p.Pass == data.Pass);
if (probableUser == null)
{
ModelState.AddModelError(string.Empty, "نام کابری یا رمز عبور اشتباه وارد شده است!");
return LogIn();
}
Session["LogedIn"] = true;
Session["UserName"] = probableUser.UserName;
Session["Course"] = probableUser.Course.Name;
Session["TeacherName"] = probableUser.Course.TeacherName;
Session["RealName"] = probableUser.RealName;
return RedirectToAction("Index", "Home");
}
and the view is like this:
#model TAPortal.Models.LoginViewModel
#{
ViewBag.Title = "ورود به سایت";
}
<h2>ورود</h2>
#using (Html.BeginForm())
{
#*#Html.AntiForgeryToken()*#
<div class="form-horizontal">
<h4>اطلاعات ورود را وارد کنید</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.UserName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Pass, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Pass)
#Html.ValidationMessageFor(model => model.Pass)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="ورود" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("برگشت به خانه", "Index","Home")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
and the model class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace TAPortal.Models
{
public class LoginViewModel
{
[Required(ErrorMessage="نام کاربری باید وارد شود!")]
[Display(Name="نام کاربری")]
public string UserName { get; set; }
[Required(ErrorMessage = "رمز عبور باید وارد شود!")]
[Display(Name = "رمز عبور")]
public string Pass { get; set; }
}
}
see these results:
input:
output local :
output on online host :
Try to add this filter
[ValidateAntiForgeryToken]
to your POST Action
Edit:
in your get method instantiate your model and set to false the ValidationSummary
[HttpGet]
public ActionResult LogIn()
{
var model = new LoginViewModel();
return View(model);
}
Now I have the answer. I share it for the others who face this problem.
From first, every thing was correct but the wrong thing was the version of the .NET framework of my host. This type of coding requires .NET framework 4.5 but my host's .NET framework version was 4.0 and it was all the story.
Now I have transferred my code to a host of 4.5.

Resources