MVC 4.0 Controller cannot find seeded data - c#

I am attempting to seed data for an MVC 4 project using SQL server 4.0 as the database engine, using the Microsoft MVC music store tutorial as an example. I have set up a seed and DB context models, but the controller is not able to find the data. I have verified that the the database file is created in App_Data and verified that SetIntitializer is correctly set up in Application_Start. Here is what I have for code:
Seed data:
namespace RationalMethodApp.Models
{
public class StartData : CreateDatabaseIfNotExists<RationalMethodEntities>
{
protected override void Seed(RationalMethodEntities context)
{
new List<Basin>
{
new Basin {
basinId = 1, // attempting to force a key value, will remove
Name = "Replace me with a real basin",
Location = "In a real location",
drainageArea = 0.0M
}
}.ForEach(b => context.Basins.Add(b));
Controller:
public ActionResult Index(int? bsnId)
{
if (bsnId == null) // here to force a key value, will change
bsnId = 1;
var basin = rmDb.Basins.Find(bsnId);
return View(basin);
}
The context class is:
namespace RationalMethodApp.Models
{
public class RationalMethodEntities : DbContext
{
public DbSet<Basin> Basins { get; set; }
public DbSet<SubArea> SubAreas { get; set; }
public DbSet<IdfCurve> IdfCurves { get; set; }
public DbSet<Analysis> Analyses { get; set; }
public DbSet<FlowSegment> FlowSegments { get; set; }
public DbSet<SheetFlowN> SheetFlowNs { get; set; }
public DbSet<RunoffCoefficient> RunoffCoefficients { get; set; }
public DbSet<StormFrequency> stormFrequencies { get; set; }
}
}
The debugger tells me that the "basin" object is still null in the controller after the .Find. This must be a simple, basic thing that I have overlooked, but all of the help I can find on-line assumes that the askers know what they are doing - not true in my case! I have also checked the discussion at Entity Framework database seed doesn't seed
but this does not seem to be the answer. Please bear with a total noob question.

You don't show the full code of you seed, so i can't really be sure, but you might be missing the Context.Changes().
As well you wrote
public class StartData : CreateDatabaseIfNotExists<RationalMethodEntities>
If you don't delete your database before the application start, it won't do anything as the db already exists.
You could use :
public class StartData : DropCreateDatabaseAlways <RationalMethodEntities>
to drop it every time you start or
public class StartData : DropCreateDatabaseAlways <DropCreateDatabaseIfModelChanges >
to drop db when Model changes (which is great for start of dev)
To debug: Drop your database, kill your application server (so it goes back to application start), breakpoint in your seed. Start Debug, if it goes in seed, check that data is in it after SaveChange().

Related

Too Many Dependency Inject

I currently have a class with around 40 dependency injection. It is a hard to maintain and unit test. I am not sure a good way around.
The code is done for any type of application process that is needed to process (New License, License Renewal, Student Registration, ...), there are around 80 different types applications and what sections are associated with each application type is determined by a database table.
I have a class with all of the possible properties, there are a several more than listed but you should get the idea. Each the properties have their own set of properties that are basic data types or object pointing to other classes.
class Application
{
[JsonProperty(PropertyName = "accounting")]
public Accounting Accounting { get; set; }
[JsonProperty(PropertyName = "application")]
public Application Application { get; set; }
[JsonProperty(PropertyName = "applicationType")]
public ApplicationType ApplicationType { get; set; }
[JsonProperty(PropertyName = "document")]
public List<Attachment> Document { get; set; }
[JsonProperty(PropertyName = "employment")]
public List<Employment> Employment { get; set; }
[JsonProperty(PropertyName = "enrollment")]
public Enrollment Enrollment { get; set; }
[JsonProperty(PropertyName = "individualAddressContact")]
public IndividualAddressContact IndividualAddressContact { get; set; }
[JsonProperty(PropertyName = "instructors")]
public List<Instructor> Instructors { get; set; }
[JsonProperty(PropertyName = "license")]
public License License { get; set; }
[JsonProperty(PropertyName = "licenseRenewal")]
public LicenseRenewal LicenseRenewal { get; set; }
[JsonProperty(PropertyName = "MilitaryService")]
public List<MilitaryService> MilitaryService { get; set; }
[JsonProperty(PropertyName = "paymentDetail")]
public PaymentDetail PaymentDetail { get; set; }
[JsonProperty(PropertyName = "photo")]
public List<Attachment> Photo { get; set; }
[JsonProperty(PropertyName = "portal")]
public Portal Portal { get; set; }
[JsonProperty(PropertyName = "section")]
public List<Section> Section { get; set; }
[JsonProperty(PropertyName = "testingCalendar")]
public TestingCalendar TestingCalendar { get; set; }
[JsonProperty(PropertyName = "testingScore")]
public List<TestingScore> TestingScore { get; set; }
[JsonProperty(PropertyName = "USCitizen")]
public USCitizen USCitizen { get; set; }
}
So this class is sent/received to an Angular 10 front end using Web API's.
When an application is requested the sections and the different properties are initiated and if the application has be started the progress will be reloaded. So it is possible some of properties will be pulled from the database and sent to the Angular app.
So I have something such as
Load(applicationTypeId, applicationId)
{
Get the sections for the application type
For each section in the sections
switch sectionid
case Documents
Load all of the documents required for the application type and get any documents uploaded
case Accounting
Load the payment details, if no payment made calculate the payment
case IndividualAddressContact
Load the person name/address/contact and set a few defaults if the person hasn't started.
.....
next
}
Save()
{
Save the application
switch current section
case Documents
Save all of the documents for the application
case Accounting
Save the payment details for the application
case IndividualAddressContact
Save the person name/address/contact for the application
.....
get the next section
Update the application current section
}
I have put all of the items in the switch into their own classes but in the end I still have 1 point for serialization/deserialization and still end up with to many dependencies injected. Creating a unit test with over 40 dependencies seems hard to maintain and given I won't know which properties will/won't used until an application is requested and loaded from database. I am unsure how to get around the switch, without at some point and time having to have all of the dependencies injected into 1 class.
I would appreciate some ideas of how to get around this.
"I currently have a class with around 40 dependency injection..." - Oh my gosh!
"It is a hard to maintain and unit test..." - I don't doubt that in the least!
SUGGESTED REFACTORING:
Create a class that manages "Applications" (e.g. "ApplicationManager").
Create an abstract class "Application".
One advantage of "abstract class" over "interface" here that you can put "common code" in the abstract base class.
Create a concrete subclass for each "Application" : public class NewLicense : Application, public class LicenseRenewal : Application, etc. etc.
... AND ...
Use DI primarily for those "services" that each concrete class needs.
I'll bet the constructors for your individual concrete classes will only need to inject three or four services ... instead of 40. Who knows - maybe your base class won't need any DI at all.
This is actually a design we're actually using in one of our production systems. It's simple; it's robust; it's flexible. It's working well for us :)
I would recommend using convention over configuration principle, with the Service Locator.
Declare something like IApplicationHandler interface in your program, e.g.
public interface IApplicationQueryHandler
{
Application Populate(Application application);
}
public interface IApplicationSaveHandler
{
Bool Save(Application application);
}
Then, write pieces of your code, with dependencies and such, e.g.
public class AccountingApplicationQueryHandler : IApplicationQueryHandler
{
public Application Populate(Application application) {
//// Load the payment details, if no payment made calculate the payment
return application;
}
}
public class AccountingApplicationSaveHandler : IApplicationSaveHandler
{
public Bool Save(Application application) {
//// Save the payment details for the application
return true; // this just flags for validation
}
}
// repeat for all other properties
Then in your controller, do something like
public class ApplicationController: Controller
{
public readonly IServiceProvider _serviceProvider;
public ApplicationController(IServiceProvider sp) {
_serviceProvider = sp;
}
public Application Load(string applicationTypeId, string applicationId)
{
var application = new Application(); // or get from db or whatever
var queryHandlers = _serviceProvider.GetServices(typeof(IApplicationQueryHandler));
foreach(var handler in queryHandlers) {
application = handler.Populate(application);
}
return application;
}
[HttpPost]
public bool Save(Application application)
{
var result = true;
var saveHandlers = _serviceProvider.GetServices(typeof(IApplicationSaveHandler));
foreach(var handler in queryHandlers) {
result = handler. Save(application);
}
return result;
}
}
You would need to register your handlers, which you can do e.g. like so:
var queryHandlers = Assembly.GetAssembly(typeof(IApplicationQueryHandler)).GetExportedTypes()
.Where(x => x.GetInterfaces().Any(y => y == typeof(IApplicationQueryHandler)));
foreach(queryHandler in queryHandlers) {
services.AddTransient(typeof(IApplicationQueryHandler), queryHandler);
}
// repeat the same for IApplicationSaveHandler
Now finally, you can write unit tests for part of the code like so
[TestClass]
public class AccountingApplicationQueryHandlerTests
{
[TestMethod]
public void TestPopulate()
{
// arrange
var application = new Application();
var handler = new AccountingApplicationQueryHandler(); // inject mocks here
// act
var result = handler.Populate(application);
// Assert
Assert.AreEqual(result. PaymentDetail, "whatever");
}
}
And you can test that your controller calls the right things by mocking IServiceProvider and injecting that with a couple of dummy handlers to confirm they are called correctly.
Following zaitsman's answer you also could create AggregatedApplicationQueryHandler and AggregatedApplicationSaveHandler and pass collection of concrete implementation of IApplicationQueryHandler and IApplicationSaveHandler to its constructor.
Then you don't need foreach loop inside controller(you loop over handlers inside aggregated handler) and always have only one handler passed to controller. Passing its by constructor parameter shouldn't be so much painful.
You also could create facade over some small services and aggregate theirs functions into one bigger facade service.

How to write code for Server side pagination in ASP.NET Core

I want to implement Server side pagination for loading of some data I want to be loaded into browser. It's working fine Client side with PageList in MVC but I don't know how to do in Asp.net Core Server side.
This is my Class There I want to show all proporties , even photo (image)
public class HouseDTO
{
[Key]
public int HouseId { get; set; }
public Nullable<decimal> Price { get; set; }
public string LiveArea { get; set; }
public string RoomAmount { get; set; }
public string HouseType { get; set; }
public string ImageName { get; set; }
}
And then my Repisitory
public interface IHouseRepository
{
public IEnumerable<HouseDTO> GetAllHouses()
}
public class HouseRepository : IHouseRepository
{
private ApplicationDbContext db;
public HouseRepository(ApplicationDbContext db)
{
this.db = db;
}
public IEnumerable<HouseDTO> GetAllHouses()
{
return db.Houses;
}
}
And this is my Controller
public class AdvController : Controller
{
private IHouseRepository db;
private IHostingEnvironment hostingEnvirnment;
public AdvController(IHouseRepository db, IHostingEnvironment hostingEnvirnment)
{
this.db = db;
this.hostingEnvirnment = hostingEnvirnment;
}
public IActionResult Index()
{
var model = db.GetAllHouses(); // How can I do this to Server side pagination?
return View(model);
}
}
So How can create Server side Pagination for this action?
public IActionResult Index()
{
var model = db.GetAllHouses();
return View(model);
}
I would greatly appreciate it if you help me.
You can use Skip() and Take(). Make a repository method that will take current position (to skip) and give parameter to Take. Something like:
public House GetPaged(currentPosition)
{
return db.Houses.Skip(currentPosition).Take(20);
}
Take() and Skip() over results of db.Houses is the way to go.
Like this:
// Skip (n) pages and take (x) elements from required page.
return db.Houses.Skip(page*countPerPage).Take(countPerPage);
// As suggested in comments for the answer above, specified code should belong to
// repository method. Initially implemented as a template to be copypasted
// and reused according to your needs.
make sure that page numbering in query is 0-based:
page = 0 if page not specified; page = 0 if you require page #1; page = 1 if you need page #2 etc. And countPerPage meaning is obvious :)
I might be a bit late for the party but I wrote a lightweight package to address this issue by giving you the toolkit to build your DB queries using Skip() and Take() as the other answers suggested.
This might be helpful for someone googling around: https://github.com/YannikG/dotnet-pageable-data

Adding a new record by using EntityFramework

I am creating a test project in order to learn using asp.net 5 and the mvc 6 framework.
I have decided to create a simple webpage that each menu item comes from the database. To do so I have created a model like such
namespace TestTemplate.Models
{
public class SideMenuItem
{
public int Id { get; set; }
public string Level { get; set; }
public string Label { get; set; }
public string Link { get; set; }
}
}
Inside my Models folder I also have a file named `TestContext.cs'
namespace TestTemplate.Models
{
public class TestContext : DbContext
{
public DbSet<SideMenuItem> SideMenuItems { get; set; }
}
}
That is my EntityFramework DbContext class.
When trying to create a new SideMenu item by using a simple view with a form to adding all the needed data, then using my angular factory that looks like this
return $resource('/api/sidemenu/:id');
I get the error:
An exception of type 'Microsoft.Data.Entity.DbUpdateException' occurred in EntityFramework.Core.dll but was not handled in user code
Additional information: An error occurred while updating the entries. See the inner exception for details.
-->System.Data.SqlClient.SqlException: Invalid object name 'SideMenuItem'.
This error occurs on SideMenuController.cs where I define my API at the part where I am trying to Post the new item:
[HttpPost]
public IActionResult Post([FromBody]SideMenuItem sideMenuItem)
{
if (sideMenuItem.Id == 0)
{
_dbContext.SideMenuItems.Add(sideMenuItem);
_dbContext.SaveChanges(); // ERROR HERE.
return new ObjectResult(sideMenuItem);
}
else
{
var original = _dbContext.SideMenuItems.FirstOrDefault(m => m.Id == sideMenuItem.Id);
original.Level = sideMenuItem.Level;
original.Label = sideMenuItem.Label;
original.Link = sideMenuItem.Link;
_dbContext.SaveChanges();
return new ObjectResult(original);
}
}
I also should mention that before running the app i used
>dnx ef migration add initial
>dnx ef database update
I believe it has to do with me not creating my database correctly. Since I am not seeing any folder on my project that had anything to do with databases or migrations.
Why is it complaining that SideMenuItem is invalid, and how can I fix the issue?
After trying to create my database again, I noticed that I had a typo on my migration command, hence the database was not created.
The command should have been dnx ef migrations ... with an s.
A good starting point with all the commands can be found here.

WEB API hangs after leaving ApiController method

My application has been built with ASP.NET MVC 4 and Web API. But I have a strange issue to share.
The corresponding code is below
public class MachinesController : ApiController
{
private GWData db = new GWData();
// GET api/Machines/5
public Machine GetMachine(int id)
{
Machine machine = db.Machines.Single(m => m.Id == id);
if (machine == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return machine;
}
Using following URL, I can examine my API Get method of a controller in Web API.
http://localhost/myweb/api/machines/1
And it worked but trying
http://localhost/myweb/api/machines/2
makes Web API hangs forever while memory usage of w3wp.exe keeps going up. So I had to eventually kill the w3wp.exe process. Further by making breakpoint inside of the GET method, I made sure that the hanging happens after getting right data and leaving the method.
How can I approach this kind of issue?
I should've found this cause earlier. This was a problem in serialization of Json. It took forever to serialize navigation properties of an entity if it has many related records. Of course, it was my fault to forget to disable lazy loading. Adding following code solved the problem.
public MachinesController()
{
db.ContextOptions.LazyLoadingEnabled = false;
}
I don't think your solution is correct. Instead you may want to have a model to view model structure, where view model object is flat and exposes only the properties you want to:
class Order
{
// properties you want to expose
public DateTime OrderDate { get; set; }
// navigation and other properties you don't want to expose
public Guid OrderId { get; set; }
public Customer Customer { get; set; }
public ICollection<Address> Addresses { get; set; }
public ICollection<Tax> Taxes { get; set; }
}
class OrderViewModel
{
public DateTime OrderDate { get; set; }
}
The easiest way to create one from another is to use AutoMapper.

C# WCF - ADO.NET Entity model - DbSet empty?

I created a new WCF project in visual studio based on a existing database.
I made two operations. One operation writes a record (createProfile) to the database and one retrieve data (GetProfiles). My project exists of 3 files: web.config, a edmx file and my svc class.
CreateProfile works fine, I checked in SQL and the record is created.
GetProfiles never gives a response. When I debug the context.UserProfileSet always counts 0 values.
Any suggestions on what is going wrong?
[DataContract]
public partial class UserProfile
{
public int Id { get; set; }
[DataMember]
public string UserName { get; set; }
}
public class MusicOwnerService : IMusicOwnerService
{
IEnumerable<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.AsEnumerable();
}
}
public void CreateProfile()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
context.UserProfileSet.Add(new UserProfile { UserName = "John" });
context.SaveChanges();
}
}
}
As far as I know, you cant pass an IEnumerable object over the wire with WCF (unless youve a duplex binding of some sort??).. so you would be best to convert to a list and return that list like below:
List<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.ToList();
}
}

Categories