Base solution for your next web application
Open Closed

Using the dynamic controllers from WPF/Xamarin host in Owin #415


User avatar
0
acrigney created

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


1 Answer(s)
  • User Avatar
    0
    acrigney created

    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.