MVC ASP - Stopping edit function from modifying fields to NULL - c#

So I'm trying to update ONLY specific data in my MVC application. Whenever I only edit a list view, I would edit the data (which works) but the rest of the database table would be NULL.
So for example -
Fields in List View
EmployeeID, FirsName, LastName, Email, Moderator, Admin
Fields not in list view
LoginID
So in my edit page, I have set up read-only for the info like EmployeeID, FirstName, LastName, and Email with two checkboxes for Moderator and Admin which are the only values I want to edit.
They work fine but when doing so, the data in the database for LoginID only becomes NULL.
Here is the code from my edit GET and POST methods
GET
public ActionResult Edit(int id)
{
EmpContext ec = new AppContext();
Employee e = ec.Employees.Single(x => x.Id == id);
return View();
}
POST
public ActionResult Edit(Employee employee)
{
if (ModelState.IsValid)
{
EmpContext ec = new EmpContext();
ec.Entry(employee).State = EntityState.Modified;
ec.SaveChanges();
return RedirectToAction("List");
}
return View(employee);
}
So, how would I stop this executing in the field LoginID within the database when there are no text boxes at all for LoginID, even on the edit page?

According to Attaching an existing but modified entity to the context
When you change the state to Modified all the properties of the entity
will be marked as modified and all the property values will be sent to
the database when SaveChanges is called.
Thus, this Entry method will update all the properties. For my recommendation, to update some Entity's columns only, you have to manually query the record and update desired properties only.
In your Edit (POST) method, change the Entry() way to:
EmpContext ec = new EmpContext();
Employee _employee = ec.Employees.Single(x => x.Id == employee.Id);
// TO-DO Update required properties only
_employee.FirstName = employee.FirstName;
ec.SaveChanges();

Related

MVC - Pulling a database field from the model and using it in the controller

I'm trying to implement a database field from the model and use it in the controller.
So for example.
In Employees.cs Model class, there is a field AccIsActive and I want to use it in the controller so I could do a conditional statement.
I want to do a conditional statement so only the list view can check if AccIsActive is true so I could show the data. I don't want to do this in the front end as it can be easily modified.
This is what I have so far in my List method.
public ActionResult List()
{
IList<Employee> employees;
EmpContext emp = new EmpContext();
employees = emp.Employees.ToList();
return View(employees);
}
I'm trying to do something like...
if (AccIsActive == true)
{
.....
}
Query the active results with linq
employees = emp.Employees.Where(e => e.AcclsActive).ToList();
return View(employees);

Adding a value in two different tables in my create controller [duplicate]

This question already has an answer here:
How to save the record mutipule table using Asp.net MVC Json
(1 answer)
Closed 3 years ago.
I have a Create controller that creates a record in one table [Kursus_kursist] using db.Add, dbSaveChanges().
I need to create a record in another table [jobcoach] based on one of the values (kursus_kursist_id which is an int), but I don't know how to pass the value.
public ActionResult Create([Bind(Include = "kursus_kursist_id,kursist_id,status, jc")] kursus_kursist kursus_kursist)
{
if (ModelState.IsValid)
{
db.kursus_kursist.Add(kursus_kursist);
db.SaveChanges();
db.jobcoach.Add(/*I THINK THE KURSUS_KURSIST_ID NEEDS TO GO HERE*/);
db.SaveChanges();
return RedirectToAction("../kursister/Index");
}
I've been able to create a record in both the usus_kursist and jobcoach tables, but in the jobcoach table I don't get the kursus_kursist_id - so basically an empty record (aside from the PK).
When you add to the database and save, that entity becomes tracked. The tracked entity have an assigned Id.
var myEntity = new SomeEntity(){
Name="Test",
CreatedDate = DateTime.UtcNow
}
dbContext.MyEntities.Add(myEntity);
dbContext.SaveChanges();
Console.WriteLine(myEntity.Id);
This will give you the proper Id EF assigned your entity.
If JobCoach is connected you could also add them in their existing relation.
var myEntity = new SomeEntity(){
Name="Test",
CreatedDate = DateTime.UtcNow,
MyChildObject = new ChildObject(){
Name="Something else",
CreatedDate = DateTime.UtcNow
}
dbContext.MyEntities.Add(myEntity);
dbContext.SaveChanges();
Console.WriteLine(myEntity.MyChildObject.Id);
So in your case you should be able to use your first kursist_thingie.Id after you saved that entity. Assign JobCoach.KursistId = kursist_thingie.Id or however you please.
Hope it helps!

Get details from a LINQ query from Controller to Razor View

Currently trying to build a bulletin in my application where the logged in user simply types in something in a text box and the results are then displayed with a list of other bulletins.
My problem is that I don't want to display the dropdown box of names, I just want the admins' ID who is logged in to post. FYI, I messed up my admin in this app, their ID is different to their userID but their usernames are the same and that is how I get their ID.
I want to store the result of a linq query in the HiddenFor in my razor page. I've been trying with ViewBags but I just get cannot implicitly convert type 'int' to 'system.collections.ienumerable'
Here is my Create part of my controller:
// GET: Bulletins/Create
public ActionResult Create()
{
string username = Membership.GetUser().UserName;
var getAdmin = (from a in db.Admins
where username == a.AdminUsername
select a.AdministrationId).SingleOrDefault();
ViewBag.AdministrationId = new SelectList(db.Admins, "AdministrationId", "AdministratorName");
return View();
}
// POST: Bulletins/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "BulletinsID,DetailsOfBulletin,AdministrationId")] Bulletins bulletins)
{
if (ModelState.IsValid)
{
string username = Membership.GetUser().UserName;
var getAdmin = (from a in db.Admins
where username == a.AdminUsername
select a.AdministrationId).SingleOrDefault();
db.Bulletins.Add(bulletins);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.AdministrationId = new SelectList(db.Admins, "AdministrationId", "AdministratorName", bulletins.AdministrationId);
return View(bulletins);
}
And my Razor View:
#Html.HiddenFor(model => model.AdministrationId)
Honestly couldn't find anything so any help would be appreciated. x
First, you should materialize your query to get all admin object from your db:
var adminIds = db.admins.Select(a => a.Id).ToList();
ViewBag.AdministrationIds = adminIds;
Then, if you are using ViewBag to access those admin ids in the view, you will need to foreach over them and render a hidden input with the ID as the value:
#{
foreach (var item in ViewBag.AdministrationIds)
{
<input type ="hidden" value="#item" />
}
}

How to ignore required field in form in Entity Framework, MVC C#

I would like to ask if its possible to ignore required field in form. Problem is i have complex form in MVC using entity framework where i want to create insurance and bind to that insurance only firm or person, not both. When i leave for example form for Person empty, it always shout out that PersonRodneCislo is required field.
Firm table and Person table are in 1...N relationship to Insurance table, coz person can have multiple insurances same as firm, but it cannot be opposite side.
For table Firm primary key is Ico
For table Person primary key is PersonRodneCislo
For table Insurance primary key is InsuranceNumber
so in my database model Insurance table has 2 foreign keys (Ico and PersonRodneCislo)
I tried use IsNullOrWhiteSpace method but problem is that it wont even reach to my create method so i have to force EF somehow to ignore one of those two field if one of them is filled
Code for [POST] Create method
public ActionResult Create([Bind(Include = "PersonRodneCislo, FirstName, LastName, Street, City, PSC, PhoneNumber, SecondaryStreet, SecondaryCity, SecondaryPSC")]Person person,
[Bind(Include = "InsuranceNumber,Premium,PaymentFrequency,AnnualDate,BeginDate,EndDate,ProductType,PersonRodneCislo")] Insurance insurance,
[Bind(Include = "Ico,Street,City,PSC")] Firm firm)
{
try
{
ViewBag.ProductType = new SelectList(db.Product, "ProductType", "ProductName");
// TODO: Add insert logic here
if (ModelState.IsValid)
{
if(String.IsNullOrWhiteSpace(firm.Ico.ToString()) && String.IsNullOrWhiteSpace(person.PersonRodneCislo.ToString()))
{
ModelState.AddModelError("Ico", "Vložte prosím IČO nebo rodné číslo");
}
if (!(String.IsNullOrWhiteSpace(firm.Ico.ToString())))
{
insurance.PersonRodneCislo = person.PersonRodneCislo;
if (!(db.Person.Any(x => x.PersonRodneCislo == person.PersonRodneCislo)))
{
db.Person.Add(person);
db.Insurance.Add(insurance);
}
else
{
db.Insurance.Add(insurance);
}
}
if (String.IsNullOrWhiteSpace(person.PersonRodneCislo.ToString()))
{
insurance.Ico = firm.Ico;
if (!(db.Firm.Any(x => x.Ico == firm.Ico)))
{
db.Firm.Add(firm);
db.Insurance.Add(insurance);
}
else
{
db.Insurance.Add(insurance);
}
}
db.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View(insurance);
}
}

How can I display data from multiple tables using a code-first approach

I'm using a code-first approach to display data from multiple tables using SQL Server. For my C# semester project, I'm building a social networking website. In my index view I want to display data from two tables, that is, from Posts and Comments.
I'm trying a lot but nothing below is in my Index action.
First, I was using this but later I think it performs only a simple join between tables.
public ActionResult Index()
{
var myobj = DB.Comments.Include("Post").ToList();
return View(myobj);
}
If I use the SQL query below instead of above inside my Index action and pass them to the view, it generates an exception. How do I avoid that?
public ActionResult Index()
{
var myobj = from u in DB.Posts
join b in DB.Comments
on u.UserID equals b.UserID
into obj
from ua in obj.DefaultIfEmpty()
select new { userComments = (ua == null) ? "" : ua.UserComments, UserPosts = u.UserPosts };
return View(myobj);
}
where inside Index.cshtml I'm using a strongly typed View:
#model IEnumerable<myApp.Models.DB.Comment>
and then display all posts and comments using a foreach loop.
But it displays only those posts which postID is present in the Comments table (foreign key from post is in the comment table).
How would I display all posts along with their comments (if any)?
I'm using an .edmx file for the backend while for retrieving/adding data from the database I'm using a code-first approach.
Here's a code example:
private SocialNetworkingEntities net = new SocialNetworkingEntities();
public void Add(RegisterView user)
{
DB.UserInfo User = new DB.UserInfo();
User.Name = user.UserName;
User.Password = user.UserPassword;
User.Email = user.UserEmail;
User.Birthday = user.UserDOB;
User.Sex = user.UserSex;
net.UserInfoes.Add(User);
net.SaveChanges();
}
If you want to display the posts with optional comments, then Post and not Comment is your main model type. Also, you don't have to manually join tables like you do in your second approach - that is done by EF automatically.
So first use the pattern of your first approch and change it to return the posts. The comments are accessible by your navigation property (Posts):
public ActionResult Index()
{
var allPosts = DB.Posts.Include("Comments").ToList();
return View(allPosts);
}
Second, change the modeltype in your view to Post:
#model IEnumerable<myApp.Models.DB.Post>
Now you should be able to enumerate all Posts and optional the Comments:
#foreach (Post post in Model) {
// display post
foreach (Comment comment in post.Comments) {
// display comment
}
}
The problem with your second approach is that your View is expecting a ViewModel of type Comment. But if you look at the query you return an anonymous type instead of a comment.
In your first query you start with Comments and load all the Posts for the comments. This way you wouldn't get posts that don't have any comments.
I think the easiest way is to define an association from Posts to Comments and change your query to:
var myobj = DB.Posts.Include("Comments").ToList();
If you then modify your View to accept a Model of type Post everything should work.

Categories

Resources