ASP.Net Application Warmup - Exposing Collections - c#

My MVC application currently uses the Global.asax, Application_Start method to load tons of data, and then exposes it as collections. For example:
Current Usage Example:
// Global.asax
public static DataRepository Repository { get; set; }
protected void Application_Start()
{
// All the normal stuff...
// Preload this repository.
DataRepository = new DataRepository();
}
// HomeController.cs Example
public ActionResult Index(){
return Json(MyApplication.Repository.GetSomeCollection(),
JsonRequestBehavior.AllowGet);
}
What I'm trying to do:
I want to use the ASP.Net 4.0 + IIS 7.5 Application Preload functionality, but need to expose the repository to the rest of the application. Something like:
// pseudo code attempt at goal
public class ApplicationPreload : IProcessHostPreloadClient
{
public MyRepositoryClass Repository { get; set; }
public void Preload(string[] parameters)
{
// repository class's constructor talks to DB and does other crap.
Repository = new MyRepositoryClass();
}
}
Question
How can I expose a repository class or even a simple IEnumerable<T> collection using the Preload() method implemented via IProcessHostPreloadClient?

If you're just aiming to expose an IEnumerable<T> try stuffing it into HttpRuntime.Cache from the implementation of IProcessHostPreloadClient. You can then optionally expose the collection from the Global.asax application class.
Something like:
public class ApplicationPreload : IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
var repository = new MyRepositoryClass();
HttpRuntime.Cache.Insert(
"CollectionName",
repository.GetCollection(),
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
null);
}
}
public class MvcApplication : HttpApplication
{
public IEnumerable<CollectionItem> CollectionName
{
get { return HttpRuntime.Cache["CollectionName"] as IEnumerable<CollectionItem>; }
}
}

Related

Should I define methods as static in class library to use in Console Application

Scenario: I have a console application which references couple of class libraries. ClassLibEmployee pulls the data from SQL database and returns a List. I need to loop through the list of Employee's and send that to a WebAPI and update SQL DB with status. I created ClassLibPay which a wrapper for WebAPI.
ClassLibEmployee.EmployeeData ed = new ClassLibEmployee.EmployeeData();
var elist = ed.PullEmployees();
foreach (Employee e in elist) {
bool stat = ClassLibPay.ServiceWrap.Sendtopay(e.Id, e.Name, e.Pay, e.ExemptFlag, e.Hours);
ed.ChageStatus(e.Id, e.Name, e.Pay, e.ExemptFlag, e.Hours, stat);
}
In ClassLibEmployee, I defined class as public class EmployeeData
In ClassLibPay, I defined class as public static class ServiceWrap
Questions:
since I will be calling ChangeStatus method in EmployeeData for each employee, should that be a static class?
ServiceWrap is calling a service, is there a way to avoid creating instance of the service, for every Sendtopay call?
Console App
--References ClassLibEmployee
public class EmployeeData
{
public List<Employee> PullEmployees()
{
}
}
ConsoleApp
--References ClassLibPay
-- ClassLibPay calls a WebAPI
public static class ServiceWrap
{
public static bool Sendtopay(int id, string name, decimal pay, bool flg, int hours)
{
using (EDataSvc service = new EDataSvc())
{
service.serviceMethod(id,name,pay,flg,hours);
}
}
}
To prevent creating every time class, you definitely should move to DI way as Michael said.
This is very simple example how to use DI with console application based on Autofac library. Below we have Main console application and two classes where one is our wrapper(where maybe you want to prepare your data, and eDataService which should just send data to back-end. We register both classes as PerLifeTimeScope(here, this is singleton's - in another words have only one instance if we get it from the DI container). Of course you can choose ready frameworks with already integrated DI containers.
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
builder.RegisterType<EDataSvc>().InstancePerLifetimeScope();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var service = scope.Resolve<MyService>();
service.MakeRequestAsync("test");
}
}
}
public class EDataSvc
{
public void SendRequestAsync()
{
//TODO:Send request
}
}
public class MyService : IMyService
{
private EDataSvc _eDataService;
public void MakeRequestAsync(EDataSvc eDataSvc)
{
_eDataService = eDataSvc;
}
public void MakeRequestAsync(string parameter)
{
//TODO prepare your data or additional logic
_eDataService.SendRequestAsync();
}
}
public interface IMyService
{
void MakeRequestAsync(string parameter);
}

How to define a public const string in a repository that implements an interface

I have a Controllerclass which makes use of a TodoRepositoryclass via DI that implements an interface ITodoRepository.
The interface:
public interface ITodoRepository
{
public bool ValidateTodo(Todo todo);
}
The repository class:
public class TodoRepository : ITodoRepository
{
public bool ValidateTodo(Todo todo)
{
//some validation
return false;
}
}
The Controller:
public TodoController : BaseController
{
private readonly ITodoRepository _todoRepository;
private const string INVALID_TODO_MESSAGE = "Invalid todo.";
public TodoController(ITodoRepository todoRepository)
{
_todoRepository = todoRepository;
}
public IActionResult Post(Todo todo)
{
if(!_todoRepository.ValidateTodo(todo))
{
return new JsonResult(INVALID_TODO_MESSAGE);
}
}
}
To be able to use INVALID_TODO_MESSAGE in every Controller that makes use of TodoRepository I want to move it to TodoRepository, but that doesn't seem to be possible. Some other solution is to create a readonly property in ITodoRepository, and implement it in TodoRepository, but I am not sure if that is the best way to go.
You could create a helper class, next to the interface:
public static class TodoConstants
{
public const string INVALID_TODO_MESSAGE = "Invalid todo.";
}
You can use it everywhere as TodoConstants.INVALID_TODO_MESSAGE.
DISCLAIMER: This is not a direct answer to the question, but rather a design suggestion for error handling in web applications.
I would implement such a validation using Exceptions. Typically you could throw business exceptions from your application layer (possibly including repository too). Then at the web layer (aka. controllers, filters, etc.) you could implement an ExceptionFilter to handle business exceptions, for example turning them into a special JsonResult.
This way you'll have a good separation of concerns and centralized error handling through the application.
See this documentation for ASP.NET WebApi (it's almost the same for MVC too) https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling
Some untested pseudo code would look like this.
public class TodoRepository : ITodoRepository
{
public bool ValidateTodo(Todo todo)
{
//some validation
throw new ValidationException("Invalid todo");
}
}
public class MyBusinessExceptionFilterAttribute : ExceptionFilterAttribute
{
public void OnException(ExceptionContext filterContext)
{
...
filterContext.Result = new JsonResult(filterContext.Exception.Message);
...
}
}
public static void ApplicationStartup() {
...
GlobalFilters.Filters.Add(new MyBusinessExceptionFilterAttribute());
...
}
public IActionResult Post(Todo todo)
{
// Just let the exception to be thrown in case of business errors
_todoRepository.ValidateTodo(todo);
}

Implementing a rich domain model in WCF where the Client objects act as remote facades

I'm working on a WCF project where I want to implement a RICH domain model where the client-side objects act as remote facades for server-side functionality but with certain shared aspects between client/server, such as validation. Let's say I have an Order class with two methods: Save() and Submit(). On the Server the Save() method would write to the database and the Submit() would send the order to a supplier's system.
I want to mirror the rich domain model on the client but instead of doing a database write in the Save() method, I want run the validation code and then call SaveOrder(this) on a WCF service interface. This would follow Fowler's Service layer + Domain model patterns. Ideally I want to write an AbstractOrder base class, implementing all shared functionality and specifying the abstract functions and then implement a ClientOrder, a ServerOrder and a WCF interface IOrderService(with Save(AbstractOrder) and Submit(AbstractOrder)) which acts as the service server-side. The ClientOrder's Save() / Submit() would call the Save/Submit methods on the IOrderService and pass itself during method call.
Is there a way to instruct WCF which objects to instantiate and deserialize the content into? I specifically want to work throughout my entire application with the Abstract version of the object and only upon deserialization figure out whether I need the Client/Server-side version of the object? We've already customized the WCF communication channels: we use protobuf combined with gzip compression for data transport between client/server and Ninject for service instantiation. Ideally I want to offload object instantiation to Ninject.
I specifically don't want the Order class to be a WCF service because I'm dealing with a fairly fat client where a large amount of logic is needed to keep the system perform within set limits and I preferably don't want to end up with an anemic domain model where most logic is stuffed into services.
In code it would like this:
[ServiceContract]
public interface IOrderService
{
[OperationContract]
AbstractOrder GetById(int id);
[OperationContract]
IEnumerable<AbstractOrder> GetBySupplier(int supplierId);
[OperationContract]
void Save(AbstractOrder order);
[OperationContract]
void Submit(AbstractOrder order);
}
public abstract class AbstractOrder()
{
public int Id { get; set; }
public string Description { get; set; }
public List<AbstractOrderline> OrderLines { get; set; }
public abstract void Save();
public abstract void Submit();
}
public class ClientOrder : AbstractOrder
{
public override void Save()
{
ValidateOrThrow();
_service.Save(this);
}
public override void Submit()
{
ValidateOrThrow();
_service.Submit(this);
}
}
public class ServerOrder : AbstractOrder
{
public override void Save()
{
ValidateOrThrow();
_unitOfWork.Save(this);
}
public override void Submit()
{
Save();
_supplierOrderService.Submit(this);
}
}
By default you cannot do this:
// Interface
AbstractOrder IOrderService.GetById(int);
// Service
AbstractOrder OrderService.GetById(int id)
{
return new ServiceOrder(...);
}
// Client
ClientOrder = (ClientOrder)IOrderService.GetById(42);
Because the order that the service returns is not a ClientOrder. Using some reflection and a custom formatter you should be able to come a long way.
Alternatively, you could rely on composition, not inheritance. Introduce an IRepository<T> (or give it a name) in your shared code and create a property for that on your model:
public interface IRepository<T>
{
void Save(T model);
void Submit(T model);
}
public class Order()
{
public int Id { get; set; }
public string Description { get; set; }
public List<AbstractOrderline> OrderLines { get; set; }
[XmlIgnore]
public IRepository<Order> Repository { get; set; }
public void Save()
{
if (Repository == null) { throw new NotSupportedException(); }
Repository.Save(this);
}
public void Submit()
{
if (Repository == null) { throw new NotSupportedException(); }
Repository.Submit(this);
}
}
Now you can inject the service- or client-specific logic thorugh this repository into your model:
// Client-specific implementation
public class ClientOrderRepository : IRepository<Order>
{
private readonly IClientOrderService _service;
public ClientOrderRepository(IClientOrderService clientOrderService)
{
_service = clientOrderService;
}
public void Save(Order order)
{
_service.Save(order);
}
public void Submit(Order order)
{
_service.Submit(order);
}
}
Then your service and client look like this:
// Interface
Order IOrderService.GetById(int);
// Service
Order OrderService.GetById(int id)
{
return new Order(...);
}
// Client
Order order = IOrderService.GetById(42);
order.Repository = new ClientRepository(...);
order.Submit();

Getting rid of HttpContext dependency - can I use thread storage instead

I'm writing WEB API service that uses a lot of legacy components. The legacy components rely heavily on calls to ContextInfo.ContextID (this is referenced like zillion of times).
public static class ContextInfo
{
public static int ContextID
{
get { return (int)HttpContext.Current.Items["ContextID"]; }
}
}
// sample legacy class
public class Legacy
{
public void Foo()
{
if (ContextInfo.ContextID == 7)
{
Bar();
}
}
}
Every single legacy web application then initializes HttpContext.Current.Items in Application_BeginRequest based on current url (domain) and some db settings.
void Application_BeginRequest()
{
HttpContext.Current.Items["ContextID"] = QueryDb(HttpContext.Current.Request.Url);
}
My web api service will have "dynamic" context. I.E.:
// sample web api method
void Get()
{
int contextID = GetContextBasedOnHttpHeader();
// Works but just icky
HttpContext.Current.Items["ContextID"] = context;
new Legacy().Foo();
}
Relying on http context in web api is just wrong. On the other rewriting all legacy components to inject contextID in a nice way is simply too much work.
I was thinking of abusing the Thread.SetData method instead - i.e.:
// sample web api method
void Get()
{
// filter would be better, but for simplicity sake
ContextInfo.ContextID = GetContextBasedOnHttpHeader();
new Legacy().Foo();
}
And rewriting the ContextInfo into something like this:
public interface IContextInfoProvider { int ContextID { get; set; } }
public class LegacyContextInfoProvider : IContextInfoProvider { ... }
public static class ContextInfo
{
public static IContextInfoProvider Provider = new LegacyContextInfoProvider();
public static int ContextID
{
return Provider.ContextID;
}
}
public class WebApiContextInfoProvider : IContextInfoProvider
{
public int ContextID {
get { return (int)Thread.GetData(Thread.AllocateNamedDataSlot("ContextID")); }
set { Thread.SetData(Thread.AllocateNamedDataSlot("ContextID"), value);
}
}
// on startup
ContextInfo.Provider = new WebApiContextInfoProvider();
We can also assume that the legacy components will run in the same thread (because you can't reference HttpContext.Current.Items once you've fired new thread - it will be null). My concern is with the thread safety - can I use it like this without any nasty side-effect ?

MVC 3 - how to implement a service layer, do I need repositories?

I am currently building my first MVC 3 application, using EF Code First, SQL CE and Ninject.
I have read a lot about using Repositories, Unit of Work and Service Layers. I think I have got the basics sorted out, and I have made my own implementation.
This is my current setup:
Entities
public class Entity
{
public DateTime CreatedDate { get; set; }
public Entity()
{
CreatedDate = DateTime.Now;
}
}
public class Profile : Entity
{
[Key]
public Guid UserId { get; set; }
public string ProfileName { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
public Profile()
{
Photos = new List<Photo>();
}
public class Photo : Entity
{
[Key]
public int Id { get; set; }
public Guid FileName { get; set; }
public string Description { get; set; }
public virtual Profile Profile { get; set; }
public Photo()
{
FileName = Guid.NewGuid();
}
}
SiteContext
public class SiteContext : DbContext
{
public DbSet<Profile> Profiles { get; set; }
public DbSet<Photo> Photos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Interface: IServices
public interface IServices : IDisposable
{
PhotoService PhotoService { get; }
ProfileService ProfileService { get; }
void Save();
}
Implementation: Services
public class Services : IServices, IDisposable
{
private SiteContext _context = new SiteContext();
private PhotoService _photoService;
private ProfileService _profileService;
public PhotoService PhotoService
{
get
{
if (_photoService == null)
_photoService = new PhotoService(_context);
return _photoService;
}
}
public ProfileService ProfileService
{
get
{
if (_profileService == null)
_profileService = new ProfileService(_context);
return _profileService;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Interface
public interface IPhotoService
{
IQueryable<Photo> GetAll { get; }
Photo GetById(int photoId);
Guid AddPhoto(Guid profileId);
}
Implementation
public class PhotoService : IPhotoService
{
private SiteContext _siteContext;
public PhotoService(SiteContext siteContext)
{
_siteContext = siteContext;
}
public IQueryable<Photo> GetAll
{
get
{
return _siteContext.Photos;
}
}
public Photo GetById(int photoId)
{
return _siteContext.Photos.FirstOrDefault(p => p.Id == photoId);
}
public Guid AddPhoto(Guid profileId)
{
Photo photo = new Photo();
Profile profile = _siteContext.Profiles.FirstOrDefault(p => p.UserId == profileId);
photo.Profile = profile;
_siteContext.Photos.Add(photo);
return photo.FileName;
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
Database.SetInitializer<SiteContext>(new SiteInitializer());
}
NinjectControllerFactory
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<IServices>().To<Services>();
}
}
PhotoController
public class PhotoController : Controller
{
private IServices _services;
public PhotoController(IServices services)
{
_services = services;
}
public ActionResult Show(int photoId)
{
Photo photo = _services.PhotoService.GetById(photoId);
if (photo != null)
{
string currentProfile = "Profile1";
_services.PhotoService.AddHit(photo, currentProfile);
_services.Save();
return View(photo);
}
else
{
// Add error message to layout
TempData["message"] = "Photo not found!";
return RedirectToAction("List");
}
}
protected override void Dispose(bool disposing)
{
_services.Dispose();
base.Dispose(disposing);
}
}
I can build my solution and it seems to be working correctly.
My questions are:
Are there any obvious flaws in my implementation that I am missing?
Will I be able to use this with TDD? Usually I see mocking of repositories but I haven't used that in the above, will that cause issues?
Am I using DI (Ninject) correctly and enough?
I am a hobby programmer, so any comments and/or suggestions to my code are welcome!
You've got the general idea, but it takes a while to really get used to Dependency Injection. I see a number of possible improvements to be made:
Your IServices interface seems unnecessary. I'd prefer to have the controller specify which services it needs (IPhotoService, etc.) via its constructor, rather than using the IServices interface like some kind of strongly-typed service locator.
Did I see a DateTime.Now in there? How are you going to verify that the date gets set correctly in a unit test? What if you decide to support multiple time zones later? How about using an injected date service to produce that CreatedDate?
There is a very good Ninject extension specifically for MVC. It takes care of plugging into the various points that MVC 3 supports for injection. It implements things like your NinjectControllerFactory. All you have to do is make your Global class extend a specific Ninject-based application.
I'd suggest using NinjectModules for setting your bindings, rather than setting them in your ControllerFactory.
Consider using Binding by Convention so that you don't have to explicitly bind each service to its implementation.
Update
The Ninject MVC Extension can be found here. See the README section for an example of how to extend the NinjectHttpApplication. This example uses Modules, which you can read more about here. (They're basically just a place to put your binding code so that you don't violate the Single Responsibility Principle.)
Regarding conventions-based bindings, the general idea is to have your binding code scan the appropriate assemblies and automatically bind things like IPhotoService to PhotoService based on the naming convention. There is another extension here to help with such things. With it, you can put code like this in your module:
Kernel.Scan(s =>
{
s.From(assembly);
s.BindWithDefaultConventions();
});
The above code will auto-bind every class in the given assembly to any interface it implements that follows the "Default" conventions (e.g. Bind<IPhotoService>().To<PhotoService>()).
Update 2
Regarding using the same DbContext for an entire request, you can do something like this (using the Ninject.Web.Common library, which is required by the MVC extension):
Bind<SiteContext>().ToSelf().InRequestScope();
Then any context-dependent services that Ninject creates will share the same instance across a request. Note that I have personally used shorter-lived contexts, so I don't know off the top of my head how you'd force the context to be disposed at the end of the request, but I'm sure it wouldn't be too difficult.
The IServices and Services types seem superfluous to me. If you drop them and change your controller's constructor to be
public PhotoController(IPhotoService photoService, IProfileService profileService)
{
_photoService = photoService;
_profileService = profileService;
}
it will be more apparent what it is actually depending on. Moreover, when you create a new controller, that only really needs IProfileService, you can just pass an IProfileService instead of a full IService, thus giving the new controller a lighter dependency.
I could argue that your services look very much with a repository. Look closely to the interface:
IQueryable<Photo> GetAll { get; }
Photo GetById(int photoId);
Guid AddPhoto(Guid profileId);
Looks very much like a repository to me. Maybe because the example is rather simple but I see the point of having a service if you add use case logic on it. instead of these rather simpel CRUD operations.
And you could argue that EFs DbSet and DbContext are the repositories and unit of work of the app...and at this point we enter a new zone that is somewhat out of scope of the question.

Categories

Resources