Retrieving related data using linq - asp.net-mvc

I have an MVC app using EF code first. I add a user to the system and enter pension details, part of this is a dropdown linked to a model called PensionBenefitLevel. This is the model -
[Key]
public int PensionBenefitLevelID { get; set; }
public string DisplayText { get; set; }
public int EmployeePercentage { get; set; }
public int EmployerPercentage { get; set; }
public virtual ICollection<Pension> Pension { get; set; }
When registered I have the PensionBenefitLevelID that came from the dropdown, but in my controller I was to peform a calculation using the EmployerPercentage value that is related to that ID. Can anyone point me in the correct direction?
Do I need to create a variable in the controller and use a linq query to get that value back? I've not been able to find any examples of something similar so if you could point me to one that would be great too.

If I understand the question correctly, you want to get back the entity corresponding to PensionBenefitLevelID and perform a calculation on the EmployerPercentage field.
Since you haven't mentioned what pattern you are using with EF (repository, unit of work, etc.) I can only give you a general answer:
var entity = [Your DB Context].[Your Entity].GetById(pensionBenefitLevelID);
if(entity != null)
{
[Calculation]
}

Related

Get only certain data from web-API get request

I made an MVC project which includes CRUD operations to all my classes, using default controllers and view pages which support those operations.
My new task was to make few API controllers to specific classes, which I have done correctly so far.
The problem is when a get request is requested, an entire object is returned with all its connections to other classes (which is correct!), but say I have this class:
public class VM{
public int Id { get; set; }
public string MacAddress { get; set; }
public string IpAddress { get; set; }
public DateTime? CreateDate { get; set; }
public string PrivateKey { get; set; }
public int AppId { get; set; }
public int CompanyId { get; set; }
}
I don't want the user to get the privateKey for instance, or ID. I would like the user to get all the rest, but certain information should NOT be sent.
What is the best practice to achieve that? Will making a new class which does not have those specific class members be the right answer?
Say tomorrow I would like to add another data member which will not be sent, will I have to make ANOTHER class?
I assume changing those specific data members' data to null just before sending the object back to the client is not the right answer, is it?
Just setting them to null is not the right answer indeed.
But generally you want your application to be as consistent as possible, and thus, for similar request you should return about the same types of fields/objects.
Thus a few (2 or 3) DTO (data transfer objects) should be sufficient.
If the project is of a small scale, or you just feel like being crazy you can always convert them to anonymous objects as follows:
List<VM> VMs = VMRepo.GetAll();
vms.ConvertAll(vm => new {vm.MacAddress, vm.IpAddress});
Or even give then custom names:
    
vms.ConvertAll(vm=> new {MAC= vm.MacAddress, IP= vm.IpAddress});

XtraGrid binding over complex and nested objects model

I'm wondering how to solve/simplify a task that sometimes pop-ups during developement with DevExpress XtraGrid suite.
Sometimes i fall into this case:
Given these 2 classes that represents the model classes that comes from the Business Logic layer:
public class Customer
{
public Int32 CustomerId { get; set; }
public String Name { get; set; }
public String Address { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public Int32 OrderId { get; set; }
public String ItemCode { get; set; }
public Int32 Quantity { get; set; }
public Decimal Price { get; set; }
public DateTime Date { get; set; }
}
I'd like to create a simple window that shows an XtraGrid that allows edit/add/remove a list of customers and its nested orders.
In order to do that, i've created a simple form with a GridControl and a GridView controls with the AllowAddRow and AllowDeleteRow properties == true.
Then, in Form1 class i've done the following:
//List of my customers
private List<Customer> _customers;
public Form1()
{
//Initialize UI components
InitializeComponent();
//Call the provider in order to get customers
CustomerProvider cp = new CustomerProvider();
_customers = cp.GetCustomers();
//Initialize bindingSource
BindingSource bs = new BindingSource();
bs.DataSource = _customers;
//Set GridControl's dataSource
gridControl1.DataSource = bs;
}
Now i've got beautiful GridControl that shows the content of my List.
But now here's the problem...how can i add or delete row?
Infact:
If i set the focus on a row and i press "Delete" key, it doesn't
work.
If i try to add a new row, when it looses focus, it suddently disappears.
Obviously i'm missing something. Unfortunately i found the DevExpress documentation a quite confusional (in my opinion) about this kind of argument and the best practises, so i can't reach my goal.
Someone can help me?
PS.
This is the hyperlink for the .csproj of my sample.
Set the gridControl1.UseEmbeddedNavigator property to true. You'll get a data navigator widget at the bottom of your view.
That only gets you halfway there, however. If you want to be able to add Orders to a Customer from the grid, your Customer class needs to use BindingList instead of List for the Orders property.
See here for more information. If you find the documentation lacking, you can also find helpful resources at the Support Center.
EDIT: Some other options to consider are:
Bind your grid to a database.
Bind to XML data and use a DataSet.
If you're already storing your data in a database, then option 1 would be the way to go. If you're not persisting your data anywhere yet, you could go either way.

ASP.net MVC - Master Detail - foreign key is always zero

I'm new to MVC and trying to add/ edit records in master detail form. Both masterid and detailid are generated by oracle on insert of record. Thus when I try to call DBContext.SaveChanges() I get error that foreign key is violated and no primary row with id '0' can be found.
Below is the class description.
public class Master
{
public int MasterID { get; set; }
public string MasterTitle { get; set; }
public virtual IList<Detail> Details { get; set; }
}
public class Detail
{
public int DetailID { get; set; }
public int MasterID { get; set; }
public string DetailName { get; set; }
public virtual Master Master { get; set; }
}
Controller code
[HttpPost]
public ActionResult Create(MASTER masterrecord)
{
if (ModelState.IsValid)
{
db.MASTER.Add(masterrecord);
db.SaveChanges();
}
...
}
The primary key (masterid) will get meaningful values only after record is inserted to database. context.SaveChanges() at this point tries to save Client records too with '0' masterid. I searched every where couldn't find anything which could be of useful.
Though of saving only Master table first so that I can retrieve the masterid and us it with DETAIL model. however couldnt find anywhere how to do it using EF5 MVC ASP.NET
Can any one point me to right direction of provide with some working sample?
thanks
Siddhant
You might want to consider using GUIDs instead of ints for your PK. Then in your constructor for Master you can say MasterID = Guid.NewGuid();. This way you don't have to hit the database to find out what the next ID will be.
There is a pro and con list here http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html
If you have set a breakpoint on the Create method and are getting a proper list in your Master object, it may be an issue with the Oracle provider.
As a workaround, you could try to change the method signature to accept your data like the following:
public ActionResult Create(MASTER masterrecord, List<Detail> details)
Then you could first save the masterrecord and subsequently add your details and save again. It's not optimal, but it may work.
Side note: change your IList to an ICollection.

MVC and EF4 CTP model-binding and saving hierarchical model

Am having trouble finding a clear answer to my situation when searching Stack Overflow and Google, hopefully someone can point me in the right direction.
My Situation
I want to be able to use a single edit form (in a single View) to update a 3-level-deep hierarchical entity using ASP.NET MVC 3 and Entity Framework 4 CTP (Code-first) - the model consists of Services, which can have many Service Options, which in Turn can have many Inventory Items.
I was expecting to be able to use MVCs default model binder (via TryUpdateModel) to:
Update an existing 'Service' record
Add/Update/Delete 'Service Option' records (attached to the Service) depending on posted values
Add/Update/Delete 'Inventory' records (attached to each Service Option) depending on posted values
My Model
[Bind(Include="Name, ServiceOptions")]
public class Service {
[Key]
public int ServiceID { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<ServiceOption> ServiceOptions { get; set; }
}
[Bind(Include="ServiceOptionID, Description, Tags")]
public class ServiceOption {
[Key]
public int ServiceOptionID { get; set; }
public int ServiceID { get; set; } /* parent id reference */
public string Description { get; set; }
public virtual ICollection<Inventory> InventoryItems { get; set; }
}
[Bind(Include = "InventoryID, Description")]
public class Inventory {
[Key]
public int InventoryID { get; set; }
public int ServiceOptionID { get; set; } /* parent id reference */
public string Description { get; set; }
}
Ideal Controller Method:
[HttpPost]
public ActionResult EditService(int id) {
Service service = db.Services.Single(s => s.ServiceID == id);
TryUpdateModel(service); // automatically updates child and grandchild records
if (ModelState.IsValid) {
db.SaveChanges();
return RedirectToAction("Index");
}
return View(service);
}
Is there a way to achieve this utopian dream, or am I barking up the wrong tree? I'm open to using another technology (such as normal EF4, Automapper etc)
Thanks in advance!
With just the default model binder? Probably not.
With a custom one? Probably.
However your issue won't be the model binder itself. Your issue will be that EF and ORMs and ( I think ) in general do not consider removing an item from a collection as a delete operation. In effect what you are telling the ORM is the relationship does not exist, not that a child row needs to be deleted. Depending on your mappings you'll usually get an error like "A referential integrity constraint violation occurred". This won't be because of code first this is just how EF works.
EF works this way by design and is really important for more complex relationships such as when you have m2m relationships which reference other m2m relationships. You really want EF to be able to disambiguate calls for removal of a relationship and calls to remove a row entirely.
Also, IMHO, this technique is also bad because your letting the piece of code responsible for mapping http values also dictate how objects should be persisted. This is a bad move. I consider delete operations a pretty sacrosanct act and shouldn't be left to the ModelBinder alone. Without soft deletes or logging deleting objects should be considered "serious business".

ASP.NET MVC bind array in model

This is somewhat a two-part question (please let me know if they should be split up).
1) I have a model class with an array of objects contained inside it. I would like to be able to bind this automatically so I can accept a single pollModel argument in my controllers.
public class pollResponseModel
{
public long id { get; set; }
public long pollID { get; set; }
public string text { get; set; }
public long count { get; set; }
}
public class pollModel
{
public long id;
public long entID { get; set; }
public string question { get; set; }
public DateTime posted { get; set; }
public DateTime expiration { get; set; }
public pollResponseModel[] responses { get; set; }
}
The problem is that I'm not sure how to bind the responses field, seeing as it can be any arbitrary size. Well, I can bind it properly when displaying the edit view, but that's about it. That leads me to the second part of my question:
2) What's an acceptable way of dynamically creating and removing data in a list on the client, so that it can be bound to a model and accessed in its modified form on the server? I envision the creation/removal process working like the iPhone list GUI: a single + button will add a new element, and a - button on each row of data will remove it from the list. I would imagine jQuery is an appropriate starting point but my JS skills are very limited.
Check out this article by Phil Haack : Model Binding To a List. It explains exactly what you need to do to bind to list properties, or properties that are complex objects.
Essentially you just have to construct your POST data in the correct way for the model binder to parse it. The article explains how to add hidden index fields and represent your complex properties in your form.

Resources