Base solution for your next web application

Activities of "acrigney"

Question

Hi Guys, Love your work, I have been building DDD frameworks myself but you've done a really great job! My client needs to use WebAPI for WPF/Xamarin apps. So I wanted to use your DynamicApiControllerBuilder to create these services from the applications and then to just resolve them in c# code on the client WPF/Xamarin side.

So I need the WPF module to dependon the ReadyCareWebApiModule [DependsOn(typeof(ReadyCareDataModule), typeof(ReadyCareApplicationModule), typeof(ReadyCareWebApiModule))] public class ReadyCareWpfModule : AbpModule

Then it looks like I can use the AbpHttpControllerSelector. SelectController mehod to get the controller i.e This method public override HttpControllerDescriptor SelectController(HttpRequestMessage request)

Then I can use the ExecuteAsync on the HttpControllerDescriptor to execute an action on the controller?

Of course we would do appropriate caching as required.

Alternatively should I write the webapi methods by hand and just call the application methods in there, but thats what we don't want to have to do right.

Best Regards, Alistair

I posted before about trying to use the dynamic web api controllers with WPF/Xamarin but I don't think I got a response yet.

I thought that I could host my webapi module in an Owin self hosting console project.

So the console program depends on my web api module

[DependsOn(typeof(ReadyCareWebApiModule))] class Program { static void Main(string[] args) { } } I came up with this so far for the statup mehod.

using Abp; using Abp.Modules; using Abp.WebApi.Configuration; // Add the following usings: using Owin; using System.Web.Http;

namespace ReadyCare.Owin.WebApi.Host { public class Startup : AbpModule { // This method is required by Katana: public void Configuration(IAppBuilder app) { AbpBootstrapper bootstrapper = new AbpBootstrapper();

        bootstrapper.Initialize();

        WindsorDependencyResolver windsorDependencyResolver = new WindsorDependencyResolver();
        windsorDependencyResolver.IocManager = this.IocManager;

        var httpConfiguration = IocManager.Resolve<IAbpWebApiModuleConfiguration>().HttpConfiguration;

        httpConfiguration.DependencyResolver = windsorDependencyResolver;

        // Use the extension method provided by the WebApi.Owin library:
        app.UseWebApi(httpConfiguration);
    }
}

}

Where the The WindsorDependencyResolver will be SOMETHING like this, based on another post you made?

public class WindsorDependencyResolver : IDependencyResolver { public IIocManager IocManager { get; set; } public override object GetService(Type serviceType) { return IocManager.IocContainer.Kernel.HasComponent(serviceType) ? IocManager.IocContainer.Resolve(serviceType) : base.GetService(serviceType); }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        return IocManager.IocContainer.Kernel.HasComponent(serviceType) ? IocManager.IocContainer.ResolveAll(serviceType).Cast<object>() : base.GetServices(serviceType);
    }
}

Maybe I need some more support, happy to discuss options. Best Regards, Alistair

I made another post on this topic but it hasn't been approved yet, lets wait for that.

Best Regards, Alistair

I am actually trying to use a Windsor IHttpControllerActivator now.

using Abp.Modules; using Castle.Windsor; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher;

namespace ReadyCare.Owin.WebApi.Host { public class WindsorCompositionRoot : AbpModule, IHttpControllerActivator { //private readonly IWindsorContainer container;

    public WindsorCompositionRoot()
    //public WindsorCompositionRoot(IWindsorContainer container)
    {
        //this.container = container;
    }

    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        var controller =
            (IHttpController)this.IocManager.IocContainer.Resolve(controllerType);

        request.RegisterForDispose(
            new Release(
                () => this.IocManager.IocContainer.Release(controller)));

        return controller;
    }

    private class Release : IDisposable
    {
        private readonly Action release;

        public Release(Action release)
        {
            this.release = release;
        }

        public void Dispose()
        {
            this.release();
        }
    }
}

}

And the startup is now

using Abp; using Abp.Modules; using Abp.WebApi.Configuration; // Add the following usings: using Owin; using ReadyCare.WebApi; using System.Web.Http; using System.Web.Http.Dispatcher;

namespace ReadyCare.Owin.WebApi.Host { [DependsOn(typeof(ReadyCareWebApiModule))] public class Startup : AbpModule { // This method is required by Katana: public new void Configuration(IAppBuilder app) { AbpBootstrapper bootstrapper = new AbpBootstrapper();

        bootstrapper.Initialize();

        GlobalConfiguration.Configuration.Services.Replace(
            typeof(IHttpControllerActivator),
        new WindsorCompositionRoot());

        var httpConfiguration = IocManager.Resolve<IAbpWebApiModuleConfiguration>().HttpConfiguration;

        //httpConfiguration.DependencyResolver = windsorDependencyResolver;

        // Use the extension method provided by the WebApi.Owin library:
        app.UseWebApi(httpConfiguration);
    }
}

}

But I get a "Object reference not set to an instance of an object." when the startup is called in the main

using Abp.Modules; using ReadyCare.WebApi; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Owin.Hosting;

namespace ReadyCare.Owin.WebApi.Host {

class Program
{
    static void Main(string[] args)
    {
        string baseUri = "http://localhost:8080";

        Console.WriteLine("Starting web Server...");
        try
        { 
        WebApp.Start<Startup>(baseUri);
        }
        catch(Exception ex)
        {
            string msg = ex.GetBaseException().Message;
        }
        
        Console.WriteLine("Server running at {0} - press Enter to quit. ", baseUri);
        Console.ReadLine();
    }
}

}

Note that my ReadyCareWebApiModule is intialising fine. like this

using System.Reflection; using Abp.Application.Services; using Abp.Modules; using Abp.WebApi; using Abp.WebApi.Controllers.Dynamic.Builders; using ReadyCare.Application; using ReadCare.ViewModels;

namespace ReadyCare.WebApi { [DependsOn(typeof(AbpWebApiModule), typeof(ReadyCareApplicationModule))] public class ReadyCareWebApiModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

        DynamicApiControllerBuilder
                   .For<IImageApplicationService<PatientBodyImageViewModel>>("telstra/readycare/ImageApplicationService")
                   .WithConventionalVerbs()
                   .Build();
        //DynamicApiControllerBuilder
        //    .ForAll<IApplicationService>(typeof(ReadyCareApplicationModule).Assembly, "telstra/readycare")
        //    .WithConventionalVerbs()
        //    .Build();

       

    }
}

}

Where I am using a generic for the ImageApplicationService as the DTOs are viewmodels for Xamarin/WPF and simple dtos for Web apps.

Question

Hi Guys, I just noticed that the latest versions of the Abp assemblies on Nuget seem to have reverted to very old versions? I have been building with Ab 0.7.1.0 Ab.Web.Api 0.7.1.0 etc.

Love your work.

Regards, Alistair

Answer

Sorry mate it was late last night! The problem was that I had not selected a target framework of net 4.5.1. Nuget really should say which framework is targeted and it would be really nice if the package info informed you that there were other releases available for other target frameworks! I guess this should be in your doco if you don't have it.

Best Regards, Alistair

Hi Guys, I have had no problems at all so far and love the framework, totally awesome design and the doco is great as well!! Just I added some unrelated code changes and now my dynamic web apis are timing out. I am completely stumped. The application service layers are just not being called from the dynamic web api. I am using Durandal and EF if that helps, I think Durandal is way better than angular for performance with large web apps.

My database connections and data are all ok.

Any help at all would be totally awesome!

Best Regards, Alistair

Awesome thanks mate. I just found the problem by turning on breaking when the exceptions are thrown, after the usual plithora of useless exceptinns .net asp mvc creates mine came up that I was missing a config setting so one of my assemblies could not be loaded.

Wow thats interesting about Durandal, so will you be doing templates for this new framework? I guess you are just using Angular but I am not really a fan.

Best Regards, Alistair

Am getting a strange issue of duplicates of my child objects getting created when I add references to these child objects in a collection. i.e When I add mobile applications to my endUser.MobileApplications I am seeing copies of my MobileApplications being created in the database. As I am only loading the MobileApplication it should not create a copy??

public async Task<long> PostNewEndUserAsync(AddEndUserInput input) { try { Logger.Debug("Adding a new end InviteUser async: " + input.Surname);

            EndUser newEndUser = Mapper.Map&lt;EndUser&gt;(input);

            newEndUser.EndUserSecurityQuestionCode = -1;
            newEndUser.AcceptedTermsAndConditions = input.AcceptedTermsAndConditions;

            if (input.MobileApplications == null)
            {
                // Add the mobile app

                if (String.IsNullOrEmpty(input.ApplicationName))
                {
                    // if none is specified use the DefaultRegistrationApplicationName 
                    input.ApplicationName = ConfigurationFacade.DefaultRegistrationApplicationName;
                }
                List&lt;MobileApplication&gt; mobileApplications = _mobileApplicationRepository.GetAllList(x => x.Name == input.ApplicationName);

                MobileApplication mobileApplication = mobileApplications.FirstOrDefault();

                if (mobileApplication == null)
                {
                    throw new Exception(String.Format("Mobile application {0} was not found to register the end user for.", input.ApplicationName));
                }

                newEndUser.MobileApplications.Add(_mobileApplicationRepository.Load(mobileApplication.Id));
            }
            else
            {
               **foreach (MobileApplicationDto mobileApplication in input.MobileApplications)
                {
                    newEndUser.MobileApplications.Add(_mobileApplicationRepository.Load(mobileApplication.Id));
                }**
            }
            long id = await _endUserRepository.InsertAndGetIdAsync(newEndUser);
            return (id);
        }
        catch (Exception ex)
        {
            string msg = ex.GetBaseException().Message;
            UserFriendlyException userFriendlyException = new UserFriendlyException(msg);
            throw userFriendlyException;
        }            
    }

Awesome yes thanks mate Automapper is the problem! I am using ignore for the mobile applications as I thought that was safer coding,

However even when I change automapper to map from the input, which has the correct loaded values (not new values), it still wants to add them. So I just put a work around for now till I can find whats wrong to clear the collection before I add the specified child values in.

Mapper.CreateMap<AddEndUserInput, EndUser>() .ForMember(x => x.Id, option => option.Ignore()) .ForMember(x => x.Patients, option => option.Ignore()) .ForMember(x => x.MobileApplications, option => option.Ignore()); //.ForMember(dest => dest.MobileApplications, opt => opt.MapFrom(src => src.MobileApplications));

public async Task<long> PostNewEndUserAsync(AddEndUserInput input) { try { Logger.Debug("Adding a new end InviteUser async: " + input.Surname);

            EndUser newEndUser = Mapper.Map&lt;EndUser&gt;(input);

            newEndUser.EndUserSecurityQuestionCode = -1;
            newEndUser.AcceptedTermsAndConditions = input.AcceptedTermsAndConditions;

            //// dummy code to get the mobile apps
            //    GetApplicationsInput getApplicationsInput = new GetApplicationsInput() { Name = null };
            //    var result = await _mobileApplicationRepository.GetMobileApplicationAsync&lt;MobileApplicationDto&gt;(getApplicationsInput);

            //    //var mobileApp = result.MobileApplications[0];

            //    input.MobileApplications = result.MobileApplications;

            if (input.MobileApplications == null)
            {
                // Add the mobile app

                if (String.IsNullOrEmpty(input.ApplicationName))
                {
                    // if none is specified use the DefaultRegistrationApplicationName 
                    input.ApplicationName = ConfigurationFacade.DefaultRegistrationApplicationName;
                }
                List&lt;MobileApplication&gt; mobileApplications = _mobileApplicationRepository.GetAllList(x => x.Name == input.ApplicationName);

                MobileApplication mobileApplication = mobileApplications.FirstOrDefault();

                if (mobileApplication == null)
                {
                    throw new Exception(String.Format("Mobile application {0} was not found to register the end user for.", input.ApplicationName));
                }

                newEndUser.MobileApplications.Add(_mobileApplicationRepository.Load(mobileApplication.Id));
            }
            else
            {
                **if (newEndUser.MobileApplications != null)
                {
                    newEndUser.MobileApplications.Clear();
                }**
                foreach (MobileApplicationDto mobileApplication in input.MobileApplications)
                {
                    newEndUser.MobileApplications.Add(_mobileApplicationRepository.Load(mobileApplication.Id));
                }
            }
            long id = await _endUserRepository.InsertAndGetIdAsync(newEndUser);
            return (id);
        }
        catch (Exception ex)
        {
            string msg = ex.GetBaseException().Message;
            UserFriendlyException userFriendlyException = new UserFriendlyException(msg);
            throw userFriendlyException;
        }            
    }
Showing 1 to 10 of 33 entries