question

DIEGOFELIPEROMEROVALDES-5270 avatar image
0 Votes"
DIEGOFELIPEROMEROVALDES-5270 asked DIEGOFELIPEROMEROVALDES-5270 commented

Assign Inventory to a Department

Hello everyone! I'm building an Inventory System where every Department has their own products list.


I have the Department table with:

PK ID - Name

I have the Inventory table with:

PK ID - Product - Category - Observations - FK DepartmentID


I want to be able to see the products separatly for every department in the system. I mean, if i select the inventory for Department 1, see the product list assigned to Department 1.


In those controllers i just have the CRUD operations. There's no problem with that. What can i do? Thank you everyone in advance.


dotnet-aspnet-mvcdotnet-entity-framework
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

cooldadtx avatar image
1 Vote"
cooldadtx answered DIEGOFELIPEROMEROVALDES-5270 commented

It would be useful if you posted your entity objects so we can better understand how you've set it up.

NOTE: I'm using Product here for your Inventory so you can just adjust the naming to meet your actual structure.

public class Department
{
   public int Id { get; set; }
   public string Name { get;set; }

   //If you want to be able to get the products by department you could expose it this way but it could be expensive if there are a lot.
   public List<Product> Products { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } //Product in DB
    public string Category { get; set; }
    public string Observations { get; set; } //??
    
    public int DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}


You'll have to set up the relationships and column names. Personally I use the fluent API but you can add attributes. I recommend you get this working first.

Now to get the products by department you can go either way (depending upon where you put your nav property).

public IEnumerable<Product> GetProductsByDepartment ( int departmentId )
{
    //Cleanest to me
    return context.Products.Where(x => x.Department.Id == departmentId);
}

//Or go the other way and load the products when the department loads (assuming you are not using lazy loading here...)
public Department GetDepartment ( int departmentId )
{
   return context.Departments.IncludeChildren(x => x.Products).FirstOrDefault(x => x.Id == departmentId);
}


· 7
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hey, thank you a LOT for your response. I believe that the first method worked! But i'm receiving an error saying departmentId parameter for GetProductsByDepartment method is NULL.

I checked my Departments Razor View and i think the problem is that the button is not sending de departmentId to the method so, how can i do that? If that's the case.


Those are the buttons in my Razor View

 @foreach (var item in Model) {
     <tr>
         <td>
             @Html.DisplayFor(modelItem => item.Name)
         </td>
         <td>
             @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
             @Html.ActionLink("Details", "Details", new { id = item.Id }) |
             @Html.ActionLink("Delete", "Delete", new { id = item.Id }) |
             @Html.ActionLink("Department Inventory", "Product", new { id = item.Id })
         </td>
     </tr>
 }

If it's not that, let me know. Thank you very much!

0 Votes 0 ·
cooldadtx avatar image cooldadtx DIEGOFELIPEROMEROVALDES-5270 ·

You're going to have to debug this if you believe the ID isn't getting back to your code. There are several places it could go wrong so you'll need to step through the various locations.

Start with the model being sent to the client. After your HTML loads in the browser look at the HTML source (in the browser) and confirm that your action link for product has the ID set properly. If it doesn't then the issue is with your action that is fetching the model to populate this view.

If the ID is correct in the HTML then the next step is the action that is being called (Product\Index I wager). Set a breakpoint on that action. Since you're specifying the Id as part of the URL your action should have a signature of something like ActionResult Index ( int id ). Confirm the parameter is set properly when the action is called. If it isn't then your problem is with the model binding as mentioned earlier.

If the Id is getting to your action then at that point you need to step through your action to see where things go wrong.

One thing to remember is that EF doesn't load nav properties by default. You're using EF (not Core) so did you enable lazy loading? If so then the nav properties will load automatically. However this is bad practice so you need to ensure that you are telling EF to load the child properties as well. In my example code notice I called Include to load the child properties as well.

0 Votes 0 ·
YijingSun-MSFT avatar image YijingSun-MSFT DIEGOFELIPEROMEROVALDES-5270 ·

Hi @DIEGOFELIPEROMEROVALDES-5270 ,
Could you post any current codes to us? It will help us to solve your problems.
Best regards,
Yijing Sun

0 Votes 0 ·

Hello YijingSun! Thank you for your response. I will post the code here.

https://pastebin.com/7enP0VTZ

@cooldadtx i did what you told me and i discovered that wasn't problem of the ID/Razor View, because it delivers the Department ID to the URL.




0 Votes 0 ·

I tried this code:

 public ActionResult Product(int departmentId = 2)
         {
             return View(db.Product.Where(x => x.Department.Id == departmentId));
         }

And i'm getting the results that i'want. But obviously it works only for the Department 2, even when i click other deparments. You have any idea?
Thanks for your time.



0 Votes 0 ·
cooldadtx avatar image cooldadtx DIEGOFELIPEROMEROVALDES-5270 ·

The problem is your parameter name in the action. In the HTML you are setting Id = 10 (for example). That translates to a URL like /product/index/10. The default routing rules understand the common parameter 'id' and call the action passing the 10 as the value of parameter 'id'. But your action has no such parameter so it is ignored. Your departmentId is an int so it will always be set to something. Since you specify a default value you get 2 every time because the URL doesn't have a value for it.

The correct solution is to change your parameter name to 'id' and remove the default value. The binding will then properly work.

If you don't want to go that route then modify the HTML to set the departmentId instead of id (e.g. new { departmentId = @Model.id }).

0 Votes 0 ·

This worked! Can't believe the solution was so easy lol. Thank you very, VERY much for your response and your time, i can continue this now.

0 Votes 0 ·