NHibernate + ASP.Net MVC + User Activity Feed - c#

I am looking for the most appropriate way of dealing with a user activity feed on my social networking site. At the moment i have several activities which can appear on the news feed such as:
Users joins the site
User comments on a post
User adds a post to their favorites
User adds a new post to the site
Here is a simplified version of my domain objects at the moment:
public abstract class NewsItem : Entity, ITenantSpecific
{
public virtual Account Account { get; set; }
public virtual DateTime DateTime { get; set; }
// returns formatted news html string which gets
// overridden by inherted classes
public abstract string GetNewsHtml();
}
public class NewsItemJoiner : NewsItem
{
public virtual Account AccountJoined { get; set; }
public override string GetNewsHtml()
{
return "XXX has just joined our music network";
}
}
As you can see at the moment I have a property which must be overridden on each activity called GetNewsHtml. This isn't ideal as I don't believe my domain should be responsible for generating my HTML.
I have thought about using a partial view for each activity type and pass into it the NewsItem base class downcasted into the correct type.
However I am open to suggestions.

I have a similar issue but with different order types. I decided to define rendering at the view layer (web/controllers), not domain. You can do it this way:
public interface IRenderer<T> where T: NewsItem
{
string Render(T item);
}
public class NewsItemJoinerRenderer: IRenderer<NewsItemJoiner>
{
public string Render(T item)
{
return "XXX has just joined our music network";
}
}
public class NewsRendererFactory
{
public IRenderer<T> GetRenderer<T>()
{
return ServiceLocator.GetInstance<IRenderer<T>>();
}
}
Then you can pass NewsRendererFactory to controller. Perhaps there's a way to avoid ServiceLocator but for now I cannot tell.
Notice that this makes your architecture both configurable and pluggable if needed.
You can define additional render-related interfaces, add more properties to the IRenderer - for example, PartialName, etc, or have lambda filters on IRenderer that Factory uses to decide if this interface implementation is applicable for the passed (to GetRenderer("some-condition")) condition. A lot of things are possible.
If you don't want IoC containers (ServiceLocator), you can have its job done with simple switch() statement inside NewsRendererFactory.GetRenderer. This will isolate the logic inside single factory method, and you'll be able to replace it easily with true IoC once you are ready.
Update: how to get renderers.
If you don't use IoC, you do something like
typeof(IRenderer<>).Assembly.GetTypes().Where(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IRenderer<>) &&
x.GetGenericArguments().FirstOrDefault() == requestedTypeArguments)
Then you can select SingleOrDefault() or ToList() if you can handle multiple renderers.

Related

ServiceStack: Is context based routing specified in the URL possible?

I'm looking to retain a ton of functionality I used to have in my codebase from the service layer that I exposed previously using OData services but through ServiceStack, assuming I implement the service logic, I don't want to have to make a ton of new DTO's for requests when this is essentially what i'm trying to achieve unless the framework "forces" me to declare a bunch of extra classes for no functional gain ...
[Route("~/{Type}")]
public class GetRequest
{
public string Type {get; set; }
public string Select { get; set; }
public string Expand { get; set; }
public string Filter { get; set; }
public string GroupBy { get; set; }
public string OrderBy { get; set; }
}
public ServiceBase<T> : Service
{
public virtual IEnumerable<T> Get(GetRequest<T> request) { ... }
}
public FooService : ServiceBase<Foo>
{
public override IEnumerable<Foo> Get(GetRequest<Foo> request) { ... }
}
The only other way I can see to implement this is to basically have to create a FooRequest DTO that inherits from the generic one here and adds nothing.
Whilst this might be the case in some scenarios, for the bulk of the hundreds of endpoints I have to migrate this just seems wasteful and likely will require to me having to result to code generation, something Service Stack claims "isn't needed".
My situation is made worse because I have "multiple data contexts" to consider for example ...
// base implementation for all services, derives from ServiceStack Service
public abstract class ServiceBase<T> : Service { ... }
// core service then one concrete implementation off that
public class CoreService<T> : ServiceBase<T> { ... }
public CoreFooService : CoreService<Foo> { ... }
/// b2b service then one concrete implementation off of that
public class B2BService<T> : ServiceBase<T> { ... }
public class BarB2BService : B2BService<Bar> { ... }
... with my OData based implementation I only need to add each new class to add a point of customisation for that type of data in the stack.
With ServiceStack this still seems to be possible regarding service classes (i think, but i'm not clear on how the routing works) ... where I get confused is understanding the request DTOs which are basically the same in all get requests but seemingly not routeable based on some tpye information in the URL.
Ideally I would like to route a standard Request DTO to a service method by a combination of the HTTP verb used and then something like [Route("~/{Context}/{Type}")] in the url (with that being the attribute usage on the DTO).
I get the feeling though that ServiceStack doesn't work like this and is going to require me to define a new DTO for literally every method on every service and i'm going to have to define a bunch of new services that don't exist with no new implementation details in them just to satisfy the frameworks needs.
Or am i missing some trick in how to use the framework here to avoid this work?
You can have multiple Service base classes but your Request DTO cannot be generic, it has to be a concrete Request DTO, but it can inherit base classes, e.g. All AutoQuery RDBMS Services inherit from QueryDb<T> or QueryDb.
Your Route should start with / (i.e. not ~/) and you could have a single Parameter that accepts any Type:
[Route("/data/{Type}")]
public class GetData
{
public string Type {get; set; }
public string Select { get; set; }
public string Expand { get; set; }
public string Filter { get; set; }
public string GroupBy { get; set; }
public string OrderBy { get; set; }
}
That can be called with:
GET /data/Anything
But your Service should have the same return Type (i.e. adhere to its Service Contract) so a wildcard Service is not going to be useful unless you return the same unstructured Data response like Dictionary<string,object>, List<object>, etc.
I get the feeling though that ServiceStack doesn't work like this and is going to require me to define a new DTO for literally every method on every service and i'm going to have to define a bunch of new services that don't exist with no new implementation details in them just to satisfy the frameworks needs.
Yes ServiceStack Requires every Service is defined by its Request DTO which is the master authority describing that Services contract. This is not just a requirement to appease the Framework, the Request DTO is the message that invokes a Service, which is the only thing generic Service Clients need to send to invoke a Service, which it can't send if it doesn't exist, nor can it have a Typed API (without code-gen) if there are no types.

Mediatr Notifications on ViewModel in WPF MVVM

While implementing a WPF Application I stumbled on the problem that my application needs some global data in every ViewModel. However some of the ViewModels only need reading access while other need read/write access for this Field. At First I stumbled upon the Microsoft Idea of a SessionContext like so:
public class SessionContext
{
#region Public Members
public static string UserName { get; set; }
public static string Role { get; set; }
public static Teacher CurrentTeacher { get; set; }
public static Parent CurrentParent { get; set; }
public static LocalStudent CurrentStudent { get; set; }
public static List<LocalGrade> CurrentGrades { get; set; }
#endregion
#region Public Methods
public static void Logon(string userName, string role)
{
UserName = userName;
Role = role;
}
public static void Logoff()
{
UserName = "";
Role = "";
CurrentStudent = null;
CurrentTeacher = null;
CurrentParent = null;
}
#endregion
}
This isn't (in my Opinion at least) nicely testable and it gets problematic in case my global data grows (A think that could likely happen in this application).
The next thing I found was the implementation of a Mediator/the Mediator Pattern from this link. I liked the Idea of the Design Norbert is going here and thought about implementing something similar for my project. However in this project I am already using the impressive Mediatr Nuget Package and that is also a Mediator implementation. So I thought "Why reinvent the Wheel" if I could just use a nice and well tested Mediator. But here starts my real Question: In case of sending changes to the global data by other ViewModels to my Readonly ViewModels I would use Notifications. That means:
public class ReadOnlyViewModel : NotificationHandler<Notification>
{
//some Member
//global Data
public string Username {get; private set;}
public async Task Handle(Notification notification, CancellationToken token)
{
Username = notification.Username;
}
}
The Question(s) now:
1. Is this a good Practice for using MVVM (It's just a Feeling that doing this is wrong because it feels like exposing Business Logic in the ViewModel)
2. Is there a better way to seperate this so that my Viewmodel doesn't need to inherit 5 to 6 different NotificationHandlers<,>?
Update:
As Clarification to what I want to achieve here:
My Goal is to implement a wpf application that manages some Global Data (lets say a Username as mentioned above) for one of its Window. That means because i am using a DI Container (and because of what kind of data it is) that I have to declare the Service #mm8 proposed as a Singleton. That however is a little bit problematic in case (and I have that case) I need to open a new Window that needs different global data at this time. That would mean that I either need to change the lifetime to something like "kind of scoped" or (breaking the single Responsibility of the class) by adding more fields for different Purposes or I create n Services for the n possible Windows I maybe need to open. To the first Idea of splitting the Service: I would like to because that would mitigate all the above mentioned problems but that would make the sharing of Data problematic because I don't know a reliable way to communicate this global data from the Writeservice to the readservice while something async or parallell running is happening in a Background Thread that could trigger the writeservice to update it's data.
You could use a shared service that you inject your view models with. It can for example implement two interfaces, one for write operations and one for read operations only, e.g.:
public interface IReadDataService
{
object Read();
}
public interface IWriteDataService : IReadDataService
{
void Write();
}
public class GlobalDataService : IReadDataService, IWriteDataService
{
public object Read()
{
throw new NotImplementedException();
}
public void Write()
{
throw new NotImplementedException();
}
}
You would then inject the view models that should have write access with a IWriteDataService (and the other ones with a IReadDataService):
public ViewModel(IWriteDataService dataService) { ... }
This solution both makes the code easy to understand and easy to test.

Is there a way to make FluentValidation more dynamic?

We just received a phase 1 release from a vendor to translate an archaic PowerBuilder application into C# MVC with Angular 5 (we have an Angular guy that has already mostly rewritten the front end in 7 so the security concerns from 5 are a nonissue). Since the statement of work only required them to reproduce the application there are next to zero validations on input because there wasn't much, if any, on the original application.
I have recently done some research into FluentValidation and like it for its reusability later in applications that will use the same overall data. However, looking at this code the models in the MVC are not normalized like they probably should be and so we have dozens of models that likely could be normalized out so that there would be less overlap in data fields such as First Name, Last Name, Address, Business Address etc.
I have basic experience with generics and reflection and have supported a few more advanced examples in the past. So I was trying to find some way to utilze these two concepts to make the validators more dynamic.
I was unable to find much in the way of more advanced FluentValidation examples other than the basic hard connection to a given named model. I have tried to use the generic T in place of the model but was unable to bridge the gap and access the object being passed into the validation.
public class FormValidator : AbstractValidator<ModelExample>
{
public FormValidation()
{
}
}
//tried to do something like this but wasn't able to access the .HasProperties. Although I was able to access the GetProperties,
//having trouble implementing it into the RuleFor however.
public class FormValidation<T> : AbstractValidator<T>
{
RuleFor(x => x.GetType().GetProperty(nameof({something if it exists}).{check stuff is valid}
{
public class ModelExample
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class OtherModelExample
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
My end goal would be to be able to pass related objects into a given validator and it would be able to determine if the properties existed and act accordingly.
This may be an issue where I don't really know how to ask the question in Google, I tend to have issue wording things in a way where it brings up what I would expect.
This also may not even be possible but if it could save me from writing a series of hard coupled validators that I might have to rewrite later if we ever are allowed to normalize the data flow it would be of great help.
Any articles or documentation with more advanced examples than the simple ones I find would be of great use even beyond this project. Most of the tutorials I find are very basic examples and I sometimes have a hard time picturing them in "real" code application.
Thanks
Instead of creating generic validators for a whole model, have you considered the reverse and creating them for each property?
If you use custom property validators you can specify the validator logic once, and then simply create a validator class per view model.
eg:
class Program
{
static void Main(string[] args)
{
var person = new Person
{
Name = "Ada",
NickName = "A"
};
var validator = new PersonValidator();
var result = validator.Validate(person);
//Should be a problem with the NickName
}
}
class Person
{
public string Name { get; set; }
public string NickName { get; set; }
}
class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.Name).SetValidator(new NameValidator());
RuleFor(x => x.NickName).SetValidator(new NameValidator());
}
}
public class NameValidator : AbstractValidator<string>
{
public NameValidator()
{
RuleFor(x => x).Must(x => x.Length > 1)
.WithMessage("The name is not long enough");
}
}
This is probably a safer option too, as it's opt in rather than implicit.

Converting an existing instance of a class to a more concrete subclass

Situation: I have a large shrink wrapped application that my company bought. It is supposed to be extensible, yada, yada. It has a DB, DAL and BLL in the form of SQL and DLLs. It also has a MVC project (the extensible part) but 95% of the "Model" part is in the DAL/BLL libraries.
Problem: I need to extend one of the "Models" located in the BLL. It is an User object with 47 properties, 0 methods and no constructor. What I started was a simple deivation of their class like:
public class ExtendedUser : BLL.DTO.User
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
}
This works fine if I just create a new ExtendedUser. However, it is populated by another call into their BLL like:
BLL.DTO.User targetUser = UserClient.GetUserByID(User.Identity.Name, id);
I tried the straight forward brute force attempt, which of course throws a Cast Exception:
ExtendedUser targetUser = (ExtendedUser)UserClient.GetUserByID(User.Identity.Name, id);
I am drawing a complete blank on this very simple OO concept. I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object. I know there is a right way to do this. Can someone slap me upside the head and tell me the obvious?
TIA
If you do want to use inheritance, then with 47 properties, something like Automapper might help you copy all the values across - http://automapper.codeplex.com/ - this would allow you to use:
// setup
Mapper.CreateMap<BLL.DTO.User, ExtendedUser>();
// use
ExtendedUser extended = Mapper.Map<BLL.DTO.User, ExtendedUser>(user);
Alternatively, you might be better off using aggregation instead of inheritance - e.g.
public class AggregatedUser
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
public BLL.DTO.User User { get; set; }
}
What about this approach (basically Aggregation):
public sealed class ExtendedUser
{
public ExtendedUser(BLL.DTO.User legacyUser)
{
this.LegacyUser = legacyUser;
}
public BLL.DTO.User LegacyUser
{
get;
private set;
}
}
I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object.
This is typically the "right" way to do this, unless you have compile time access to the BLL. The problem is that a cast will never work- an ExtendedUser is a concrete type of User, but every User is not an ExtendedUser, which would be required for the cast to succeed.
You can handle this via aggregation (contain the instance of the User as a member), but not directly via inheritance.
This is often handled at compile time via Partial Classes. If the BLL is setup to create the classes (ie: User) as a partial class, you can add your own logic into a separate file, which prevents this from being an issue. This is common practice with many larger frameworks, ORMs, etc.

FluentValidation Validator using arguments

I have a FluentValidation validator that I want to use to validate a booking. On a booking you must choose a room type that exists as an available room type on the tour that you are choosing. I need to get the available room types from a service, passing in the code for the tour. What is the best way to handle getting the tour code where it needs to be?
What I've got so far:
public class BookingValidator : AbstractValidator<Booking>, IBookingValidator
public BookingValidator()
{
RuleFor(booking => booking.Rooms).SetValidator(new RoomValidator())
}
public class RoomValidator : AbstractValidator<Room>
public RoomValidator()
{
//validate that room.Type (eg. TWIN) exists in availableRoomTypes (eg List<string> {'SINGLE','TWIN'}
}
Some hack at the problem:
public class BookingValidator : AbstractValidator<Booking>
//should/can i pass in arguments here when IoC container is wiring up IBookingValidator to BookingValidator? Seems awkward
public BookingValidator(string tourCode)
{
//if so, use argument to get available room types, pass to RoomValidator
var availableRooms = RoomTypeService.GetAvailableRoomTypesForTour(tourCode);
RuleFor(booking => booking.Rooms).SetValidator(new RoomValidator(availableRooms))
//alternatively, tourCode is available from booking - is there some way to pass it to RoomValidator?
RuleFor(booking => booking.Rooms).SetValidator(new RoomValidator(),booking => booking.TourCode);
//Or is there some way I should be using .Must() or Custom()??
}
So the main problem is how or where to get tour code into the validator...?
I would suggest creating a service that has dependencies on IRoomTypeService and IBookingValidator. It gets the available room types from the IRoomTypeService dependency and passes them to the validator via a property. See the following code by way of example:
public class BookingValidationService : IBookingValidationService
{
public IRoomTypeService RoomTypeService { get; set; }
public IBookingValidator BookingValidator { get; set; }
public ValidationResult ValidateBooking(Booking booking, string tourCode)
{
BookingValidator.AvailableRooms = RoomTypeService.GetAvailableRoomTypesForTour(tourCode);
return BookingValidator.Validate(booking);
}
}

Categories

Resources