I am using ninject.extensions.conventions to bind all implementations in a given assembly and tag them with the assembly name as the binding's metadata. I can pull these items back out using a Get and supplying a func as standard.
What I would like to know is does this func apply to all children resolved also? My worry is that while my logic works now, if I add more bindings that satisfy any children more than once ninject will throw.
Code Sample:
_kernel.Bind(binder => binder.From(new[] { pathToAssembly })
.SelectAllClasses()
.BindAllInterfaces()
.Configure(binding =>
binding.WithMetadata("context",
assemblyName)));
_kernel.Get<IRootDependency>
(metadata => metadata.Get<IRootDependency>("context") ==
assemblyName);
// Bound from convention above.
RootDependencyBase: IRootDependency
{
Public RootDependencyBase(IChildDependency Child) {};
}
// Bound using the convention above with the same MetaData Tag.
ChildDependencyFromSameAssembly : IChildDependency {}
// Bound using a differing convention and does not have the same MetaData tag.
ChildDependencyFromOtherAssembly : IChildDependency {}
Based on the above sample I know that IRootDependency will be resolved to the correct binding based on the metadata filter.
What I am looking to find out is is the following true.
This filter does not feed down the dependency chain. IChildDependency will throw an exception because although the binding specified MetaData it is not queried.
Constraints are applyed to the root resolution only. In case you have multiple assemblies containing a child dependency you will get an exception.
To get it work you have to add a condition to the bindings. E.g like this:
.When(r => r.ParentContext == null || r.ParentContext.Binding.Metadata.Get<string>("context", null) == assemblyName)
Or get the root request (request.ParentRequest until parentRequest is null) and apply the constraint
.When(r => GetRootRequest(r).Constraint(r))
Yes, in case if your examples will has another implementation of IChildDependency in same assembly as ChildDependencyFromSameAssembly you'll get exception ActivationException with message:
Error activating IDependency
More than one matching bindings are available.
You have to provide exact criteria to Ninject to find what implementation of IChildDependency, from same assembly, will suits better
Related
Base entity interface is IEntity which requires only "object ID {get;set;}" to be implemented.
Now, in almost every case ID is of Guid type (except for membership etc).
I am using following code to do mapping of interface
...
AnyPart<IEntity> primaryMap = ReferencesAny(x => x.Primary)
.IdentityType<object>() // tried with .IdentityType<Guid>()
.EntityIdentifierColumn("PrimaryID")
.EntityTypeColumn("PrimaryType")
.MetaType<string>();
...
Of course, next I am adding meta values.
So, Now getting error
Source array was not long enough. Check srcIndex and length, and the array's lower bound
And with .IdentityType<Guid>()
could not resolve property: Primary.ID of: Founder.Connection [.SingleOrDefault[Founder.Connection](NHibernate.Linq.NhQueryable`1[Founder.Connection], Quote((x, ) => (OrElse(AndAlso(Equal(x.Primary.ID, 35c2142a-4c17-4b77-96fd-a2570028a211), Equal(x.Secondary.ID, 35c2142a-4c17-4b77-96fd-a2570028a211)), AndAlso(Equal(x.Secondary.ID, 35c2142a-4c17-4b77-96fd-a2570028a211), Equal(x.Primary.ID, 35c2142a-4c17-4b77-96fd-a2570028a211))))), )]
UPDATE:
I tried also with .IdentityType(x=>x.ID) but same problem (Source array was not long enough)
UPDATE II:
Query (Actually whole method containing query) that this error occurs on is bellow:
public IQueryable<Connection> GetConnections(IEntity connectable)
{
IQueryable<Connection> query =
Query().Where(
x => x.Primary.ID == connectable.ID || x.Secondary.ID == connectable.ID);
return query;
}
Try this in the query: x.Primary == connectable (without ID).
The problem is that you reference an object (or another unmapped type, that's why you need an any mapping). There is no ID on object.
By the way, using HQL would allow you to access the id by using the keyword id, which is not available in Linq (technically it could be made available as extension method, but I don't know Linq to NH good enough to say if it had been implemented). Every any reference conceptually has an id and a class.
crosspost: https://orchard.codeplex.com/discussions/459007
First question I have is what would be the repercussions of having 2 PartHandlers for the same Part in 2 different modules?
I got into this predicament because I have to run a method once a specific Content Type is created. It would be as easy to hook onto OnCreated for the part, however, here is my scenario:
Module A contains the part and the original handler
Module B contains the service where the method is
Module B has a reference to Module A
Therefore, I am unable to reference Module B within Module A (circular reference). So what I did was to copy the exact same PartHandler in Module A and placed it in Module B.
Would anything be wrong with that?
Then comes my second question, which I think could solve all these problems: Can we create a PartHandler for the Content Item's default Content Part? (i.e. the part where all custom fields are attached to)
This would definately make things easier as I could consolidate stuff that need to run there.
UPDATE 1 (to better explain question 2)
ContentDefinitionManager.AlterPartDefinition("EventItem",
builder => builder
.WithField("StartDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly")
.WithSetting("DateTimeFieldSettings.Required", "true"))
.WithField("StartTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("EndDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
.WithField("EndTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("Intro", cfg => cfg
.OfType("TextField")
.WithDisplayName("Intro")
.WithSetting("TextFieldSettings.Flavor", "textarea"))
ContentDefinitionManager.AlterTypeDefinition(
"EventItem"
, cfg =>
cfg
.DisplayedAs("Event Item")
.WithPart("TitlePart")
.WithPart("EventItem")
.WithPart("LocationPart")
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("CommonPart")
.Draftable()
.Creatable()
);
I'm talking about creating a ContentHandler for the EventItem part which holds all the custom fields. How can I go about it when EventItemPart is not defined in any class in the solution?
The following below won't work since it can't find the class EventItemPart:
OnCreated<EventItemPart>((context, keynotes) =>
questionService.SetDefaultQuestions(context.ContentItem));
Cross-answer as well.
Bertrand's perfectly right. Why do you need to reference B in A in first place? If the service from B needs A and A needs this service, then it belongs to A (at least the interface - contract).
You can always split interface and actual implementation for your service, having one in different module than another. If implementation of your service requires stuff from B, then put the interface in A, but actual implementation in B. This way A doesn't even need to know about the existence of B, but still be able to use the service via it's interface - it's the beauty of IoC pattern and Orchard modularity:)
You may use ContentPart or IContent as a type argument in handler generic methods. It's perfectly valid. This way you'd be able to plug in to events on all items, and perform custom filtering afterwards (based on type name, some field existence etc.). In your case it may look like:
OnCreated<ContentPart>((context, part) =>
{
if(part.ContentItem.ContentType != "EventItem") return;
questionService.SetDefaultQuestions(context.ContentItem);
});
Update: no need to do this: .WithPart("EventItem"). This 'fake' part will be automatically added by framework.
Cross-answer:
none
However, repeating yourself is almost always wrong, especially if it's done for a bad reason. Why is are the service and the part in two different modules? Why does A need B? A circular reference indicates tight coupling. If the tight coupling is justified, then it should happen in a single module. If it's not, then you need to re-do your design to remove it.
You can create a handler for anything, but your explanation of your scenario is way to vague and abstract to give any useful advice.
I'm exploring using FluentValidation as it seems to be an elegant API for validation of my ViewModels upon model binding. I'm looking for opinions on how to properly centralize validation using this library as well as from my business (service) layer and raise it up to the view without having 2 different approaches to adding modelstate errors.
I'm open to using an entirely different API but essentially looking to solve this branching validation strategy.
[Side Note: One thing I tried was to move my business method into my FluentValidation's custom RsvpViewModelValidator class and using the .Must method but it seemed wrong to hide that call in there because if I needed to actually use my Customer object they I would have to re-query it again since its out of scope]
Sample Code:
[HttpPost]
public ActionResult AcceptInvitation(RsvpViewModel model)
{
//FluentValidation has happened on my RsvpViewModel already to check that
//RsvpCode is not null or whitespace
if(ModelState.IsValid)
{
//now I want to see if that code matches a customer in my database.
//returns null if not, Customer object if existing
customer = _customerService.GetByRsvpCode(model.RsvpCode);
if(customer == null)
{
//is there a better approach to this? I don't like that I'm
//splitting up the validation but struggling up to come up with a
//better way.
ModelState.AddModelError("RsvpCode",
string.Format("No customer was found for rsvp code {0}",
model.RsvpCode);
return View(model);
}
return this.RedirectToAction(c => c.CustomerDetail());
}
//FluentValidation failed so should just display message about RsvpCode
//being required
return View(model);
}
[HttpGet]
public ActionResult CustomerDetail()
{
//do work. implementation not important for this question.
}
To give some closure to the question (and make it acceptable) as well as summarize the comments:
Business/process logic and validation logic are two entities. Unless the validation ties in to the database (e.g. check for unique entries) there's no reason to group validation into one location. Some are responsible in the model making sure there's nothing invalid about the information, and some handle how the validated values are used within the system. Think of it in terms of property getters/setters vs the logic used in the methods with those properties.
That being said, separating out the processes (checks, error handling, etc.--anything not relating to UI) can be done in a service layer which also tends to keep the application DRY. Then the action(s) is/are only responsible for calling and presenting and not performing the actual unit of work. (also, if various actions in your application use similar logic, the checks are all in one location instead of throw together between actions. (did I remember to check that there's an entry in the customer table?))
Also, by breaking it down in to layers, you're keeping concerns modular and testable. (Accepting an RSVP isn't dependent on an action in the UI, but now it's a method in the service, which could be called by this UI or maybe a mobile application as well).
As far as bubbling errors up, I usually have a base exception that transverses each layer then I can extend it depending on purpose. You could just as easily use Enums, Booleans, out parameters, or simply a Boolean (the Rsvp either was or wasn't accepted). It just depends on how finite a response the user needs to correct the problem, or maybe change the work-flow so the error isn't a problem or something that the user need correct.
You can have the whole validation logic in fluent validation:
public class RsvpViewValidator : AbstractValidator<RsvpViewModel>
{
private readonly ICustomerService _customerService = new CustomerService();
public RsvpViewValidator()
{
RuleFor(x => x.RsvpCode)
.NotEmpty()
.Must(BeAssociatedWithCustomer)
.WithMessage("No customer was found for rsvp code {0}", x => x.RsvpCode)
}
private bool BeAssociatedWithCustomer(string rsvpCode)
{
var customer = _customerService.GetByRsvpCode(rsvpCode);
return (customer == null) ? false : true;
}
}
I would like to know how to configure NHibernate "mapping by code" so that when I map a property of a certain type, it uses a certain userType to perform that mapping. It figures this out by convention.
For example, if I have an Account class with a property Currency of type Currency, then the NHibernate configuration should figure out (by convention) that it needs to use the CurrencyUserType to perform the mapping.
I'm unable to find the relevant documentation for this, so if such documentation does exist, then a few links will be appreciated too.
Note: This is not a FluentNHibernate question.
var mapper = new ConventionModelMapper();
mapper.IsProperty((info, b) => b || info.GetPropertyOrFieldType() == typeof(Currency));
mapper.BeforeMapProperty +=
(inspector, member, customizer) =>
{
if (member.LocalMember.GetPropertyOrFieldType() == typeof(Currency))
customizer.Type<CurrencyUserType>();
};
Ok, each and every time I get into this situation, I struggle back and forth until I find a way to solve it (and that is usually not the way I would have liked to solve it).
What I'm talking about is disconnected entities in EF that should update existing entities in the database.
I'll give an example of my problem here (this example is the last time I got into this problem that caused me to write this question).
I have a WCF service that uses Entity Framework as well. The other program that have added a service reference to my service have gotten proxy versions of the Entities as normal.
The case is that the consumer of the service now construct a object of this proxy class, and call the method UpdateEntity on the WCF service. This entity has a foreign key to another type of entities, and the primary key of the entity I want to link this new entity to is also sent as a parameter to this method. In this case, I want the entity with the same primary key in the database to be updated. It seems simple enough right?
My method looks something like this now:
public bool ChangeEntity(MyEntity entity, int otherTableForignKey)
{
//first I verify that the entity to update exist in the system
var entitytochange = entityContext.MyEntities.FirstOrDefault(e => e.Name == entity.Name);
if (systemtochange == null) return false;
try
{
entity.ForignEntity = entityContext.ForeignEntities.FirstOrDefault(f => f.Key == otherTableForignKey);
//code for updating the entity should go here, but I'm nor sure what
entityContext.SaveChanges();
return true;
}
catch (Exception exc)
{
return false;
}
}
I tried many different combinations of ApplyCurrentValues, Attach, setting ObjectState to Modified and so on, but I get either the error message that I can't add a new entity with the same key as an existing entity, that the object state of the new object can't be Added and so on.
So my question is: What is the best way to do this without writing code that looks like a big hack.
The only way I got this working now was to just set the properties of entitytochange manually with the properties of entity, but it is a bad solution since any added properties to MyEntity will break the code if I don't remember to add code in this method as well, and it seems there really should be another way that is better.
EDIT
When I put entityContext.MyEntities.ApplyCurrentValues(entity); where my comment is put above, I get the following exception on this line:
The existing object in the ObjectContext is in the Added state. Changes can only be applied when the existing object is in an unchanged or modified state.
However, if I remove this line above entity.ForignEntity = entityContext.ForeignEntities.FirstOrDefault(f => f.Key == otherTableForignKey); then the ApplyCurrentValues works without any problems.
Why would me setting the ForeignEntity of the object set it to Added state? So it seems that setting a Property on the Detached entity, attaches it to the context with a state of added?