MVC ViewModel - how to approach this requirement - c#

I have what is (I'm sure) quite a simple issue to fix, as it must be a common requirement. However, I'm new to this and can't seem to find the information that can help me work it out.
My Domain Model:
-Project (ID, ProjectName, Client)
Actor (ID, ProjectId, Title, Description)
On my CRUD for Actors I want to show Project Name as a readonly field (my application already knows which project I want to add actors to).
So, I need to create a view model which get's me the project name and all of my actors for that project. Here is what I have so far:
public class ActorsViewModel
{
//properties
public string projectName {get; set;}
public List<Actor> projectactors {get; set;}
//constructor
public ActorsViewModel (int projectId)
{
//TODO
/*
project = //get the project name from the projects table
projectActors = //get all of the actors for this project
*/
}
My aim is that on the index, the actors will be listed with their project name. In edit and create, the form will automatically be populated with the project name (and it will be readonly - I plan to do this by adding an attribute to the HTML Helper.
Can anyone give me some advice/point me in the right direction?

This would need to go in your controller:
public ActionResult Edit(int projectId)
{
using(var context = new CustomDbContext())
{
var model = new ActorsViewModel()
{
projectName = context.Projects.FirstOrDefault(p => p.Id = projectId).Name,
projectactors = context.Actors.Where(a => a.ProjectId == projectId).ToList()
}
}
return View(model);
}
Note that you would rather not create the context like this in your controller, but rather have it injected (or using a service or something). This is just to get you going, not showing best practices.
But you do want any logic in the Web project in your controller, not in your view model.

To make sure the name can not be changed you may hide it in your viewmodel by removing the setter of the property and initialize the name during construction.
public class ActorsViewModel
{
public ActorsViewModel(){} //Default ctor for modelbinder and co
public ActorsViewModel(string projectName)
{
ProjectName = projectName;
}
public string ProjectName {get; }
public List<Actor> ProjectActors {get; set;}
}
The disadvantage is that in your Post Controller Actions you need to either add the projectId/ProjectName to the request or look it up every time.

Related

c# filter database results using EF similar to SQL WHERE Clause

I've connected to my database using Entity Framework and am building my first MVC app for use in a web page.
I can get the controller to populate public strings in my models with no problem... the issue I'm having is that I can't figure out how to filter responses from my database.
I expect to have only one item returned which I will display in the view with #Model.BusinessUnit
Here's my Model Class for the database table:
public partial class TBL_Wholesale_UWS_BusinessUnits
{
public int PrimaryID { get; set; }
public string BusinessUnit { get; set; }
public string Status { get; set; }
}
Here's what I have in my controller:
public ActionResult test(int PrimaryID)
{
var testing = new TBL_Wholesale_UWS_BusinessUnits();
// maybe putting new is the wrong thing to do as that would be wiping the class? IDK
return View(testing);
}
As you can see, the PrimaryID is passed to the controller via the querystring and this is recognised without issue, but I'm at a loss as to where to add the filter, I assumed it would be something like...
var testing = TBL_Wholesale_UWS_BusinessUnits.Where(TBL_Wholesale_UWS_BusinessUnits.PrimaryID = PrimaryID);`
but Visual Studio is telling me in no uncertain terms that this this wrong.
Had this been classic asp I would have just made a record set and used the where clause in SQL, but as this is built with the Entity Framework to do my connecting I don't really know where to start.
Any help would be greatly appreciated.
If you are only trying to return that one specific object to the view.. then you need to find that int PrimaryID in the database and retrieve that specific record.
What you are doing is simply creating a new instance of the TBL_Wholesale_UWS_BusinessUnits class which is empty.
Try this:
public ActionResult test(int PrimaryID)
{
var testing = db.TableName.Find(PrimaryID);
// db = Whatever the variable holding your connection string is.. maybe DbContext
// TableName = Whatever table in your database that holds the record you want
// This will return the specific object that you are looking for
return View(testing);
}
I hope this helps!

MVVM View Model Collections with Web API, View Model and Entity Framework

question about collection helper classes for view models with in a Web API <> View Models <> Entity Framework <> Database structure.
I'm trying to get a design started on a project which will use an "API" front end to get data, then HTML/Javascript pages to get and render.
In trying to create an MVVM approach to this I am not sure if what I want to implment is a good approch or not.
And that is a get Collection methods for the ViewModels. The user on the HTML side, will only be able to edit one Object at a time, so the collection is only to provide arrays/listing of the objects, making the Web API classes "less cluttered".
Using the Visual Studio MVC/Web API porject / c# (Visual Studio 2013 so MVC 5 components)
so using example of a Chair object
NOTE: in actual code would not do "new MyEntity().Chairs." all the time, it would be set as a variable with in the class. Simply written example long hand to make clear.
Web API part:
we will pluralize api objects front point
Web API controller = ChairsController
With 2 gets
namespace FurnitureAPI.Controllers
{
[Authorize]
public class ChairsController : ApiController
{
// GET api/chairs
public IHttpActionResult Get()
{
var chairs = ViewModels.Chairs.Get();
return Ok(chairs);
}
// GET api/chairs/5
//public string Get(int id)
public IHttpActionResult Get(int id)
{
var chair = ViewModels.Chairs.Get(id);
return Ok(chair);
}
public ... GET() {...} //all chairs
public ... GET(int id) {} //single chair where id
In the database side, we have Chair table. This will be singular for database.
Database already exists, so using Entity Framework and database first modelling we get in Entities
var furniture_db = new Models.FurnintureEntities();
and
Models.Chair
So in the middle want a View Model Chair.
namespace FurnitureAPI.ViewModels {
public class Chair {
public int ChairID { get; set; }
public string Name { get; set; }
public Chair() { }
public Chair(int chairid, string name) {
ChairID = chairid;
Name = name;
}
public Chair(Models.Chair db_chair) {
ChairID = db_chair.ChairID;
Name = db_chair.Name;
}
}
In my thinking, the Web API ChairsController I do not want to have any entity framework code.
but I want api to call something to get a List/Collection of Chair view models
So Im thinking, add Chairs as a class in the ViewModel namespace, which will be static.
so web api becomes
public IHttpActionResult Get()
{
var chairs = ViewModels.Chairs.Get();
return Ok(chairs);
}
and the View Model Collection Chairs then looks like
namespace FurnitureAPI.ViewModels {
public static class Chairs {
public static List<Chair> Get() {
List<Chair> chairs = (from s in new Models.FurnintureEntities().Chairs
select new ViewModel.Chair {
ChairID = s.ChairID,
Name = s.Name
}).ToList();
return chairs;
}
public static Chairs Get(int id) {
var chair = new FurnitureEntities().Chairs.SingleOrDefault(c => c.ChairID == id);
return chair != null ? new ViewModel.Chair(chair) : null;
}
}
So the question, is this Chairs collection wrapper okay/ideal/bad/run for the hills/other, or is there a different approach someone could point to?
I do not understand why struggling to find reference to on the internet, sure hope its not grumpy old age kicking in.
I find lots of WPF MVVM Entity Framework database first stuff, but I just want to make 'simple' Web API to expose the database to make HTML views with.
Maybe I do not need to bother with the View Model and simply serialize the Entity in the Web API methods?
Thanks.
Unfortunately I've been struggling with this too and it seems this subject doesn't get the love it should have.
Anyway, among the tools there are, you can count:
Breeze# (MIT)
TrackableEntitities (MIT)

Model inheritance - Repository Pattern with IoC

I am new to IoC and Repository Pattern. I was able to do some test project and it works. But, I am not so sure if what I implemented is a good practice. The test project I have created have all the repositories in place as well as a working interface with a dummy data. But what I want is that my project should not be able to know the concrete types of my models because the initial version should be implemented using MSSQL, and the second version would be a mix of MSSQL and NoSQL(for reads and logging). The models might have different properties or structures from MSSQL to NoSQL (or whatever i might use in the future)
So I tried to create an interface for each model:
public interface ISearchResult
{
string Id { get; set; }
string Name { get; set; }
string Description { get; set; }
string Url { get; set; }
}
And here's the repository:
public interface ISearchRepository<T> where T: class, ISearchResult
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
And here's the service:
public interface ISearchService
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
Because I want to have a working GUI even without MSSQL or NoSQL entities, I have created a View Model that inherited the ISearchResult:
public class SearchResultViewModel : ISearchResult
{
[Display(Name="Reference Id")]
public string Id { get; set; }
[Display(Name = "Company")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Website")]
public string Url { get; set; }
}
And here's how it looks on my controller:
[SearchQueryFilter]
[GeoTargetFilter]
public ActionResult Query(SearchQueryModel searchQuery)
{
searchQuery.Results = this._searchService.Search<SearchResultViewModel>(searchQuery.Keyword,searchQuery.Region, new List<string>() { searchQuery.Industries }, new List<string>() { searchQuery.Countries}, new List<string>() {searchQuery.City}, searchQuery.Offset)
.ToList<ISearchResult>();
return View(searchQuery);
}
And my view would look like this:
#foreach (SearchResultViewModel result in Model.Results)
{
//code to display
}
My question is: Is it fine to use this approach? I don't want my web application to be dependent on my data entities so that's why I came up of making my view models inherit an interface. And because I was new to IoC and Repository Pattern and only have a test project, I don't know if my solution would be more of a problem in the long run.
Any advise is highly appreciated.
You shouldn't need to implement an interface in your view model in order to create a separation between your web application and your data entities. Your view model should belong to your web application and should itself be independent of your data entity.
So, instead of:
_searchService.Search<SearchResultViewModel>(x);
You should have, in your controller:
var result = _searchService.Search<SomeEntity>(x);
var model = new SearchResultsViewModel
{
Name = result.Name,
Desc = result.Desc,
Url = result.Url
};
return View(model);
The view model belongs to the web application and is responsible for containing the data passed from controller to view (and back) - it should have nothing to do with your service layer (or any other layer of your application).
SomeEntity is a concrete class, in the form of whatever your search service exposes. Your controller will consume this in the same way as any other application would and then compile a view model for passing to and from views. You might even find that SomeEntity is more or less identical to SearchResultsViewModel initially; however, they are still distinct entities as the requirements of the view might change independently of the search service.

How to initialize on MVC module?

I am new to MVC programming. In normal OOP, where I have my class, I would just initiliaze and load data from database. In MVC, we have modules, how do I load up records from it?
Here is my current code for type UserAcount:
[Table("UserAccount")]
public class UserAccount {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string userName { get; set; }
public string email { get; set; }
public int companyID { get; set; }
}
Say that I have an user with name "testUser", how do I initialize on this record and get it's information? How do I do this:
UserAccount user = new UserAccount("tesetUser");
How and where shoulud I use this?
user = user.SingleOrDefault(u => u.userName.ToLower() == User.Identity.Name.ToLower());
You need to read up on Entity Framework. This is the default ORM that MVC uses. Simply:
If you don't have a project context, yet, create one:
public class MyProjectContext : DbContext
{
public MyProjectContext()
: base("name=ConnectionStringNameHere")
{
}
}
Add your models to your project context:
public class MyProjectContext : DbContext
{
...
public DbSet<SomeModel> SomeModels { get; set; }
public DbSet<SomeOtherModel> SomeOtherModels { get; set; }
# etc.
}
Update your database using Package Manager Console (TOOLS > Library Package Manager > Package Manager Console):
> update-database
(hit ENTER after typing that)
Now, to use your context in your controllers:
public class MyAwesomeController : Controller
{
private MyProjectContext db = new MyProjectContext();
public ActionResult Index()
{
var someModels = db.SomeModels;
return View(someModels);
}
public ActionResult GetSomeModel(int id)
{
var someModel = db.SomeModels.Find(id);
return View(someModel);
}
# other actions
}
In the simplest case, you should do this logic in your controller, which will pass the data to the view. However, MVC is meant for UI separation of concerns, so theoretically you should be doing this in your domain layer, which is called from your controller.
Here is a decent article from Jeff Atwood, however I disagree that the controller is the brains of the application. It is more of the brains of the UI...but that depends on how complex your code is. Dont create a domain layer if it is stupidly simple
In the MVC model, Controllers are responsible for processing HTTP requests.
Typically you would load your entity (e.g. UserAccount) in a controller action.
If you want to edit / update an entity, typically you would map the relevant fields to a model that reflects the UserAccount. A separate model is suggested because the needs of the UI are often somewhat different than the needs of the entity model. Having separate classes for each concern avoids polluting the entity model to satisfy the needs of the view.

Passing DTO to my ViewModels constructor to map properties

In my solution I have two projects.
Project 1 (Core)
Mapping SQL to DTO using Dapper
Project 2 (WebUI - ASP.NET MVC 4)
Here I use a ViewModel per View.
Examples of a Controller
[HttpGet]
public ActionResult Edit(int id)
{
// Get my ProductDto in Core
var product = Using<ProductService>().Single(id);
var vm = new ProductFormModel(product);
return View(vm);
}
Examples of a ViewModel
public class ProductFormModel : BaseViewModel, ICreateProductCommand
{
public int ProductId { get; set; }
public int ProductGroupId { get; set; }
public string ArtNo { get; set; }
public bool IsDefault { get; set; }
public string Description { get; set; }
public string Specification { get; set; }
public string Unit { get; set; }
public string Account { get; set; }
public decimal NetPrice { get; set; }
public ProductFormModel(int productGroupId)
{
this.ProductGroupId = productGroupId;
}
public ProductFormModel(ProductDto dto)
{
this.ProductId = dto.ProductId;
this.ProductGroupId = dto.ProductGroupId;
this.ArtNo = dto.ArtNo;
this.IsDefault = dto.IsDefault;
this.Description = dto.Description;
this.Specification = dto.Specification;
this.Unit = dto.Unit;
this.Account = dto.Account;
this.NetPrice = dto.NetPrice;
}
public ProductFormModel()
{
}
}
Explanation:
I'll get my DTOs in my controller using a service class in the project (Core).
Then i create my ViewModel and pass the DTO to the constructor in ViewModel.
I can also use this view to add a new Product because my ViewModel can take a empty constructor.
Does anyone have experience of this. I wonder if I am in this way will have problems in the future as the project gets bigger?
I know this has nothing to do with Dapper. But I would still like a good way to explain my solution.
I think you will be fine using your current approach. More importantly, start out like this and refactor if you start to encounter problems related to your object mapping code (instead of thinking too much about it beforehand).
Another way to organize mapping logic that I use sometimes is to employ extension methods. That way, the mapping code is kept separate from the view model itself. Something like:
public static class ProductMappingExtensions
{
public static ProductFormModel ToViewModel(this ProductDto dto)
{
// Mapping code goes here
}
}
// Usage:
var viewModel = dto.ToViewModel();
Yet another approach would be to use a mapping framework like AutoMapper - this is a good fit in particular if your mapping logic is simple (lots of 1:1 mappings between properties).
But again, start simple and refactor when you need to.
I realize that this is a little bit late answer, but maybe it will help someone in the future.
This way of doing mapping between objects breaks the 'S' of the SOLID principles, because the responsibility of the ViewModel is to prepare data in its properties to be ready to use by the view and nothing else, therefore, mapping objects should not be on it's responsibilities.
Another drawback of this way is that it also breaks the 'Loose Coupling' OO principle as you ViewModel is strongly coupled with your DTO.
I think, even when we are in the very first step of the project, there are some importants OO principles that we should never break, so using mapper classes, either auto (AutoMapper, ValueInjecter ...) or manual, is definitely better.

Categories