Here is my case, I wrote a wcf and it is working with orchard perfectly.
I'm going to handle events messages such as warnings and exceptions so I add a ServiceAdapter
and ClientServiceLocator to my project :
ServiceAdapter:
public class ServiceAdapter<TService>
where TService : class, IContract
{
public TResult Execute<TResult>(Func<TService, TResult> command)
where TResult : IDtoResponseEnvelop
{
try
{
var dispatcher = ClientServiceLocator.Instance().CommandDispatcher;
var result = DispatchCommand(() => dispatcher.ExecuteCommand(command));
if (result.Response.HasWarning)
{
ClientServiceLocator.Instance()
.WarningManager
.HandleBusinessWarning(result.Response.BusinessWarnings);
}
if (result.Response.HasException)
{
ClientServiceLocator.Instance()
.ExceptionManager
.HandleBusinessException(result.Response.BusinessException);
}
return result;
}
finally
{
}
}
private static TResult DispatchCommand<TResult>(Func<TResult> dispatcherCommand)
where TResult : IDtoResponseEnvelop
{
var asynchResult = dispatcherCommand.BeginInvoke(null, null);
while (!asynchResult.IsCompleted)
{
}
return dispatcherCommand.EndInvoke(asynchResult);
}
}
ClientServiceLocator:
public class ClientServiceLocator
{
static readonly Object LocatorLock = new object();
private static ClientServiceLocator InternalInstance;
private ClientServiceLocator() { }
public static ClientServiceLocator Instance()
{
if (InternalInstance == null)
{
lock (LocatorLock)
{
// in case of a race scenario ... check again
if (InternalInstance == null)
{
InternalInstance = new ClientServiceLocator();
}
}
}
return InternalInstance;
}
#region IClientServices Members
public IBusinessExceptionManager ExceptionManager { get; set; }
public IBusinessWarningManager WarningManager { get; set; }
public ICommandDispatcher CommandDispatcher { get; set; }
#endregion
}
BusinessExceptionManager:
class BusinessExceptionManager
: IBusinessExceptionManager, IDependency
{
private Localizer T { get; set; }
private readonly INotifier _notifier;
public BusinessExceptionManager(INotifier notifier)
{
_notifier = notifier;
T = NullLocalizer.Instance;
}
public void HandleBusinessException(BusinessExceptionDto exceptionDto)
{
_notifier.Add(NotifyType.Error, T(exceptionDto.Message));
}
}
BusinessWarningManager:
class BusinessWarningManager
: IBusinessWarningManager, IDependency
{
private Localizer T { get; set; }
private readonly INotifier _notifier;
public BusinessWarningManager(INotifier notifier)
{
_notifier = notifier;
T = NullLocalizer.Instance;
}
public void HandleBusinessWarning(IEnumerable<BusinessWarning> warnings)
{
var message = string.Join(Environment.NewLine, warnings.Select(w => w.Message));
_notifier.Add(NotifyType.Warning, T(message));
}
}
Here is the controller:
public class SectorsAdminController : Controller
{
private dynamic Shape { get; set; }
private Localizer T { get; set; }
private readonly INotifier _notifier;
private readonly ISiteService _siteService;
private ServiceAdapter<ISectorService> _sectorServiceAdapter;
public SectorsAdminController(ISiteService siteService, INotifier notifier, IShapeFactory shapeFactory)
{
Shape = shapeFactory;
T = NullLocalizer.Instance;
_notifier = notifier;
_siteService = siteService;
_sectorServiceAdapter = new ServiceAdapter<ISectorService>();
}
public ActionResult Index()
{
var model = Shape.Sectors(Sectors: _sectorServiceAdapter.Execute(s => s.FindAll()).Sectors);
return View((object)model);
}
}
Here is the error:
Oops. Something went wrong ... sorry
An unhandled exception has occurred and the request was terminated. Please refresh the page. If the error persists, go back
Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object. Server stack trace: at SAS.Admin.Services.ServiceAdapter1.<>c__DisplayClass31.b__0() at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData) at System.Func1.EndInvoke(IAsyncResult result) at SAS.Admin.Services.ServiceAdapter1.Execute[TResult](Func2 command) at SAS.Admin.Controllers.SectorsAdminController.Index() at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.b__3f() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.b__41() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.b__41()
Why would you use a Poor's Man Singleton? I would start by using ISingletonDependency on your IClientServices members, if that is what you need
Get rid of the horrible ServiceLocator, then add IDependency to your ServiceAdapter.
As matter of fact change everything to let Orchard handle instantiation. I do not see why your ServiceAdapter could not be a simple Service instantiated by your Controller, then each one of your IClientServices created as Providers in your Service.
Related
Is there a way I can override getter of RowKey property for TableEntity ?
I would assume that it is possible to use the new keyword to override the getter as such:
public class Person : TableEntity
{
public Person(string name, string surname)
:base(surname, name)
{
}
public new string PartitionKey
{
get { return "OhLala" + base.PartitionKey; }
}
public new string RowKey
{
get { return "ohMama" + base.RowKey; }
}
}
Here is the snippet to implement the ITableEntity interface
public class TestEntity : ITableEntity
{
private string _rowKey;
public TestEntity()
{
this.Properties = new Dictionary<string, EntityProperty>();
}
private IDictionary<string, EntityProperty> Properties { get; set; }
public void ReadEntity(IDictionary<string, EntityProperty> properties, Microsoft.WindowsAzure.Storage.OperationContext operationContext)
{
this.Properties = properties;
}
public IDictionary<string, EntityProperty> WriteEntity(Microsoft.WindowsAzure.Storage.OperationContext operationContext)
{
return this.Properties;
}
}
I am having below mentioned POCO classes.
public class AppointmentModel
{
public InvoiceDetail InvoiceDetails { get; set; }
public Invoice Invoice { get; set; }
}
public class InvoiceDetail
{
public Invoice Invoice { get; set; }
}
public class Invoice
{
public Invoice()
{
Id = Guid.NewGuid(); Created = DateTime.Now;
}
public Guid Id { get; set; }
public virtual Appointment Appointment { get; set; }
}
I have tried to add that model inside repository is as below.
public void Booking(AppointmentModel appointmentModel)
{
appointmentModel.InvoiceDetails.Invoice.LatestTotal = latestinvoiceTotal;
Catalog.Appointments.Add(appointmentModel.InvoiceDetails.Invoice.Appointment);
Catalog.SaveChanges();
}
It gives below mentioned error.
An entity object cannot be referenced by multiple instances of
IEntityChangeTracker
Stack Trace is as below.
at System.Data.Objects.ObjectContext.VerifyContextForAddOrAttach(IEntityWrapper wrappedEntity)
at System.Data.Objects.ObjectContext.AddSingleObject(EntitySet entitySet, IEntityWrapper wrappedEntity, String argumentName)
at System.Data.Objects.DataClasses.RelatedEnd.AddEntityToObjectStateManager(IEntityWrapper wrappedEntity, Boolean doAttach)
at System.Data.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach)
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
at System.Data.Objects.DataClasses.EntityReference`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)
at System.Data.Objects.DataClasses.RelationshipManager.AddRelatedEntitiesToObjectStateManager(Boolean doAttach)
at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)
at System.Data.Entity.Internal.Linq.InternalSet`1.<>c__DisplayClass5.<Add>b__4()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at PawLoyalty.Data.PetBookings.Repositories.InvoiceRepository.Booking(AppointmentModel appointmentModel) in d:\PawLoyalty Module\New Booking Flow\NewBookingFlow\PawLoyalty\PawLoyalty.Data\PetBookings\Repositories\InvoiceRepository.cs:line 339
at PawLoyalty.Business.Invoices.InvoiceService.Booking(AppointmentModel appointmentModel) in d:\PawLoyalty Module\New Booking Flow\NewBookingFlow\PawLoyalty\PawLoyalty.Business\Invoices\InvoiceService.cs:line 38
at PawLoyalty.Business.BookingFacadeService.Booking(AppointmentModel appointmentModel) in d:\PawLoyalty Module\New Booking Flow\NewBookingFlow\PawLoyalty\PawLoyalty.Business\BookingFacadeService.cs:line 152
at PawLoyalty.Web.Controllers.PetBookingController.BookingProcess(String providerKey, String ownerKey, String serviceId, String petKeys, String selectedDates, String selectedExtraServices, String selectedResourceId, String key, String type) in d:\PawLoyalty Module\New Booking Flow\NewBookingFlow\PawLoyalty\PawLoyalty.Web\Controllers\PetBookingController.cs:line 243
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
UPDATE
It's coming through BasicRepository is as below.All repositories have been inherited from this.
public class BasicRepository : IBasicRepository
{
private DataCatalog catalog;
protected DataCatalog Catalog { get { if (catalog == null) catalog = new DataCatalog(); return catalog; } }
public void Dispose() { if (catalog != null) catalog.Dispose(); }
}
Can I have any help ?
I have domain class with following definition
public class Category : EntityBase<int>
{
public string Name { get; set; }
public string Description { get; set; }
}
And this class is inherited from a common abstract class
public abstract class EntityBase<TId>
{
public TId Id { get; set; }
}
And my ServiceModel class for this type is look like
public class CategoryDto
{
public string Name { get; set; }
public string Description { get; set; }
public int CategoryId { get; set; }
}
to convert between object i am using automapper. i configured automapper like this
public class AutoMapperServiceConfigurations
{
public static void Configure()
{
Mapper.Initialize(conf => conf.AddProfile(new CategoryProfile()));
}
}
public class CategoryProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Category,CategoryDto>();
}
}
to convert objects when i used automapper in my code it shows some error, my code is given below
var categoryCollection= _categoryRepository.Get<Category>();
// Mapping section here i got error
var returnCollection =
Mapper.Map<IQueryable<Category>, IQueryable<CategoryDto>> (categoryCollection);
return returnCollection;
and the error is
<Error><Message>An error has occurred.</Message><ExceptionMessage>
Unable to cast object of type
'System.Collections.Generic.List`1[PCD.Service.ServiceModels.CategoryDto]' to type 'System.Linq.IQueryable`1[PCD.Service.ServiceModels.CategoryDto]'.
</ExceptionMessage><ExceptionType>System.InvalidCastException</ExceptionType><StackTrace> at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source)
at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
at PCD.Service.Implimentations.CategoryService.Read[T]() in g:\AngularJs Practise\ProofOfConceptDemo.Solution\PCD.Service\Implimentations\CategoryService.cs:line 50
at PCD.WebApi.Controllers.CategoryController.Get() in g:\AngularJs Practise\ProofOfConceptDemo.Solution\PCD.WebApi\Controllers\CategoryController.cs:line 23
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)</StackTrace></Error>
You will want to use the queryable extensions:
http://docs.automapper.org/en/stable/Queryable-Extensions.html
var categoryCollection = _categoryRepository.Get<Category>();
var returnCollection = categoryCollection.ProjectTo<CategoryDto>();
return returnCollection.ToList();
Seeing a strange problem, getting empty metata pages for xml,json and jvs.
Using the following command line app. How does one debug these issues?
namespace ConsoleApplication2
{
public struct NativeUser
{
public int login;
public string group;
public string name;
}
[DataContract]
public class User
{
private NativeUser _native;
public User() { }
public User(NativeUser native)
{
_native = native;
}
public static implicit operator NativeUser(User user)
{
return user._native;
}
public static implicit operator User(NativeUser native)
{
return new User(native);
}
// ReSharper disable InconsistentNaming
[DataMember]
public int login
{
get { return _native.login; }
set { _native.login = value; }
}
[DataMember]
public string group
{
get { return _native.group; }
set { _native.group = value; }
}
[DataMember]
public string name
{
get { return _native.name; }
set { _native.name = value; }
}
}
[Description("GET account, all or by list of groups or by list of logins")]
[Route("/accounts/{groups}", "GET")]
[Route("/accounts/{logins}", "GET")]
[Route("/accounts/", "GET")]
public class Accounts : IReturn<User[]>
{
public string[] groups { set; get; }
public int[] logins { set; get; }
public Accounts() { }
public Accounts(params int[] logins)
{
this.logins = logins;
}
public Accounts(params string[] groups)
{
this.groups = groups;
}
}
public class Host : AppHostHttpListenerBase
{
public Host() : base("Test",
typeof(Accounts).Assembly)
{
}
public override void Configure(Funq.Container container)
{
}
}
public class Servce : IService
{
public object Get(Accounts request)
{
return new List<User>(){new User(new NativeUser())};
}
}
class Program
{
static void Main(string[] args)
{
var host = new Host();
host.Init();
host.Start("http://+:12345/");
global::System.Console.ReadLine();
}
}
}
Nm, found the bug :
public class Accounts : IReturn<User[]>
needs to be
public class Accounts : IReturn<List<User>>
Another very note worthy thing: All DTO's and objects being passed back and fourth in the DTO's require an empty constructor in order for the metata data to be properly generated.
Not sure if this is by design or a bug
is there any problem with this kinda registration via structure map??
static public class ContainerBootstrapper
{
static public void BootstrapDefaultContainer(bool test = false)
{
StructureMap.ObjectFactory.Initialize(x =>
{
x.Scan(p =>
{
p.AssemblyContainingType<IPropertyType>();
p.AddAllTypesOf<IPropertyType>();
// p.AddAllTypesOf<IPropertyType>().NameBy(c => c.Name);
});
});
}
public interface IPropertyType : IIdentityObject, IPriority
{
string PropertyName { get; set; }
ObjectType ObjectType { get; }
string DisplayName { get; set; }
IEntityType EntityType { get; set; }
IList<IPropertyRuleObject> RuleObjects { get; set; }
void AddRuleObject(IPropertyRuleObject ruleObject);
}
public abstract class PropertyTypeBase : PersistentObject, IPropertyType
{
public PropertyTypeBase()
{
}
public PropertyTypeBase(string propertyName, string displayName)
{
PropertyName = propertyName;
DisplayName = displayName;
}
....
}
public class StringType : PropertyTypeBase
{
private ObjectType _objectType;
public StringType()
{
_objectType = new ObjectType(typeof(string));
}
public StringType(string propertyName, string displayName)
: base()
{
PropertyName = propertyName;
DisplayName = displayName;
}
public override ObjectType ObjectType
{
get { return _objectType; }
}
}
when ContainerBootstrapper.BootstrapDefaultContainer(); execute I see this line of error:
StructureMap Exception Code: 200
Could not find an Instance named "StringType" for PluginType Azarakhsh.Domain.Core.AdaptiveObjectModel.Interface.IPropertyType
the calling code:
public IPropertyType GetPropertyType(IIdentityObject identityObject, string name)
{
string[] Properties = name.Split('.');
object Result = identityObject;
foreach (var Property in Properties)
Result = Result.GetType().GetProperty(Property).PropertyType.Name;
IPropertyType propertyType = StructureMap.ObjectFactory.GetNamedInstance<IPropertyType> (Result + "Type");
if (propertyType==null)
throw new Exception("Property type not found");
return propertyType;
}
what is the problem?
You are trying to get a named instance, but from what I can see of the code you have provided, you dont name your instances. The line of code that name your instances is commented out.
But even if you would just use the ObjectFactory.GetInstance<IPropertyType>(); here, you would have got an error because structuremap dont know what constructor to use. There are several solutions to theis problem.
Change your design so you only have one constructor
Mark your default constructor with the [DefaultConstructor] attribute, then it will work.
You can register it with objectFactory manually with something like this:
x.For().Use().Ctor("propertyName").Is("someValue").Ctor("displayName").Is("someValue");
You can write a custom registrationconvention as described here