ServiceStack - Different server to main application - servicestack

I wish to create a service which will be hosted on Server A (eg URL: http://servera:807). But my main application needs to be hosted on Server B (eg URL: http://serverb:801).
I am curious if this is possible or not? The reason my service and main application need to be on different servers are for reasons beyond my control. The current system uses WCF with the same setup and I'd like to move away from this.
In the examples the Service and Client all seem to be hosted in the same location / in the same solution

Below is a potential set up for solutions/projects. It's simplistic and incomplete but I think helps illustrate one possible set up. You would also need to consider how you want to handle Session information and Authentication since the MVC and ServiceStack handle this separately. See CustomAuthenticationMVC
ServerA.sln (ASP.NET Web Application)
ServiceModel project - holds requests objects and dtos (this can be shared between ServerA and ServerB solutions)
ServiceInterface project - has the Service implementations
Global.asx - has Application_Start method to configure ServiceStack
ServerB.sln (MV4 application)
ServiceModel project (shared)
Views
Models
Controllers
Example of classes in ServiceModel Project:
[Route("/Foos")]
public class Foos : IReturn<FoosResponse>
{}
public class FoosResponse
{
public FoosResponse()
{
this.ResponseStatus = new ResponseStatus();
}
public ResponseStatus ResponseStatus {get; set;}
}
Examples of classes in ServiceInterface project
public class FoosService : Service
{
public FoosResponse Get(Foos request)
{
return new FoosReponse();
}
}
Example how to call ServiceStack API within MVC4 application
public class FoosController
{
public ActionResult Index()
{
var client = new JsonServiceClient("http://servera:807");
var response = client.Get(new Foos());
return View(response);
}
}

Related

I have to integrate ServiceStack together with Kephas. How do I make them both play together with Dependency Injection?

ServiceStack uses a dialect of Funq (no support for metadata), where Kephas uses one of MEF/Autofac (requires metadata support). My question has two parts:
How to make ServiceStack and Kephas use one DI container, if this is possible?
Depending on the answer above: how to make ServiceStack services (like IClientCache) available to Kephas components, knowing that such services may not be annotated with [AppServiceContract]?
You can make ASP.NET and Kephas use one container by choosing to work with Autofac. However, as #mythz pointed out, you will need to provide the Autofac IoC Adapter to the ServiceStack. I don't think you will have any problems with ASP.NET in doing so, as Autofac is the first recommendation of the ASP.NET Core team.
For ASP.NET Core, reference the Kephas.AspNetCore package and inherit from the StartupBase class if you need to be all setup. However, if you need to be in control, have a look at https://github.com/kephas-software/kephas/blob/master/src/Kephas.AspNetCore/StartupBase.cs and write your own Startup class. Another resource that you might find useful is the Kephas.ServiceStack integration package.
Then, additionally to annotating service contracts and service implementations, Kephas allows you to provide service definitions by implementing the IAppServiceInfoProvider interface. These classes are automatically discovered, so this is pretty much everything you have to do.
public class ServiceStackAppServiceInfoProvider : IAppServiceInfoProvider
{
public IEnumerable<(Type contractType, IAppServiceInfo appServiceInfo)> GetAppServiceInfos(IList<Type> candidateTypes, ICompositionRegistrationContext registrationContext)
{
yield return (typeof(IUserAuthRepository),
new AppServiceInfo(
typeof(IUserAuthRepository),
AppServiceLifetime.Singleton));
yield return (typeof(ICacheClient),
new AppServiceInfo(
typeof(ICacheClient),
ctx => new MemoryCacheClient(),
AppServiceLifetime.Singleton));
}
}
Note in the above example that for IUserAuthRepository there is no implementation provided. This indicates Kephas to auto-discover the implementation in the types registered for composition. Alternatively, feel free to use an instance or a factory in the registration, if you need to be deterministic.
I've never heard of Kephas before, but if you're referring to this Kephas Framework on GitHub it says it uses ASP.NET Core in which case it's best if you get them to both use ASP.NET Core's IOC which you can do by either registering your dependencies in ConfigureServices in your App's Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//...
}
}
Or alternatively in ServiceStack's latest v5.6 release for Modular Startup change your ASP.NET Core Startup class to inherit from ModularStartup, e.g:
public class Startup : ModularStartup
{
public Startup(IConfiguration configuration) : base(configuration){}
public new void ConfigureServices(IServiceCollection services)
{
//...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
}
}
In which case you'll be able to Register ASP.NET Core dependencies in AppHost by registering them in your AppHost's Configure(IServiceCollection) where they can be resolved through both ASP.NET Core's IOC + ServiceStack's IOC, e.g:
public class AppHost : AppHostBase
{
public override void Configure(IServiceCollection services)
{
services.AddSingleton<IRedisClientsManager>(
new RedisManagerPool(Configuration.GetConnectionString("redis")));
}
public override void Configure(Container container)
{
var redisManager = container.Resolve<IRedisClientsManager>();
//...
}
}

ASP.NET Core Directory.EnumerateDirectories not working when deployed to Azure AppService

I am currently experimenting with ASP.NET Core MVC by creating a simple blog with static views. I've created a custom class that implements the IViewLocationExpander in order to enumerate a directory structure to retrieve razor views
public class FolderEnumerationViewExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context,
IEnumerable<string> viewLocations)
{
var locations = viewLocations.ToList();
foreach (var directory in Directory.EnumerateDirectories("Views/Blog", "*", SearchOption.AllDirectories))
{
locations.Add($"/{directory.Replace("\\","/")}" + "/{0}.cshtml");
}
return locations.AsEnumerable();
}
}
I've configured this class to be used within Startup.cs's ConfigureServices method
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IPostsMetaDataRepositry>(new JsonPostsMetaDataRepository(ConfigurationPath.Combine("posts.json")));
services.Configure<RazorViewEngineOptions>(o => { o.ViewLocationExpanders.Add(new FolderEnumerationViewExpander()); });
services.AddMvc();
}
This seems to work perfectly when I run my application locally using IISExpress however, when I deploy the application to an Azure AppService, only a handful of the directories within ~/Views/Blog are being enumerated when trying to locate views.
I'm fairly certain the issue is one of configuration but I am having a difficult time tracking down what it could be. Any ideas as to why this may be occurring?
I have the full source of this project on GitHub for reference: https://github.com/pstricker/Develothink

Azure Mobile Services - No bootstrapper found

I have a Azure Mobile Services project. When running locally everything works fine, the Application_Start() method gets called which in turn calls my WebApiConfig.Register() method.
However, when published to a live Azure Mobile Services server the Application_Start() does not get called along with the WebApiConfig.Register().
In the servers log I have the following entry:
No bootstrapper found -- using default bootstrapper. A bootstrapper can be specified in one of two ways: Either by defining a public, static class with name 'WebApiConfig' having a public parameter-less member called 'Register', or using the 'IBootstrapper' attribute to define a public class with a default constructor.
Why is Azure Mobile Services not picking up my BootStrapping WebApiConfig?
public static class WebApiConfig
{
public static void Register()
{
Trace.TraceInformation("Hello from WebApiConfig Register().");
// Use this class to set configuration options for your mobile service
ConfigOptions options = new ConfigOptions();
// Use this class to set WebAPI configuration options
HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));
// To display errors in the browser during development, uncomment the following
// line. Comment it out again when you deploy your service for production use.
// config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
}
}
public class WebApiApplication : System.Web.HttpApplication
{
public WebApiApplication()
{
Trace.TraceInformation("Hello from WebApiApplication ctor!");
}
protected void Application_Start()
{
Trace.TraceInformation("Hello from Application_Start()");
//RouteConfig.RegisterRoutes(RouteTable.Routes);
WebApiConfig.Register();
var dataContext = new DataContext();
dataContext.Database.Initialize(false);
}
}
Help is much appreciated!
That is bizarre... It really looks like you got it right. After working with .net backend azure mobile service for few weeks, I might suggest just maybe restart the service in portal and republish. I have hit some weird unexplained stuff just like you are and somehow fix like that.

Using MVC5 Repository pattern but need advice on where to put business logic

My latest MVC solution consists of an MVC5 site and a DAL class library that will contain a repository interface and class for each entity. I am trying to figure out where to place business logic for my entities such as CheckingAccount.Withdrawl or CheckingAccount.Deposit. Any suggestions? Should this be done within the Model folder within the MVC project while all of the repository classes are in my DAL?
Ideally you want to separate your actual business logic from your entities and abstract it away from your database or ORM as much as possible by creating a business logic layer and injecting your repository into your service/business logic layer using an IoC container and dependency injection.
The common approach is to create a separate class library for your business logic layer that remains agnostic of your UI layer (meaning your UI layer could be an MVC front end or even restful web service) and communicates via data transfer objects.
Here is a simple example:
MVC Controller / UI
public class AccountCheckingController : Controller
{
private readonly IAccountService AccountService;
public CheckingAccountController(IAccountService accountService)
{
this.AccountService accountService;
}
[HttpPost]
public ActionResult Deposit(decimal depositAmount)
{
...
DepositReceiptDto depositReceipt = this.accountServive.Deposit(accountId, depositAmount);
...
return new DepositViewModel {
Receipt = depositReceipt
}
}
}
Business Logic Class / Service (stored in a class library such as WebsiteName.Services or Website.BusinessLogic
public class AccountService : IAccountService
{
private readonly IAccountRepository Repository;
public AccountService(IAccountRepository repository)
{
this.Repository = repository;
}
public DepositReceiptDto Deposit(int accountId, decimal depositAmount)
{
// Perform actions against your repository/ORM here.
return new DepositReceiptDto {
DepositAmount = depositAmount,
User = UserDto,
Status = Status.Success
};
}
...
}
As you can see, by using this separation you can easily switch out your UI without having to perform much work.
I hope this helps.
If something is not an entity and is not a value object, then it's a service. Correct namespace for service depends on his level. Data-access services may be located in the Project.Dal or Project.Dal.Services. The good namespace for domain's service is the Project.Domain.Services.

NServiceBus Unit of Work For Multitenancy with Custom ORM

Here are my parameters:
Simple NServiceBus Saga implementation using the default builder
In-house ORM on top of SQL Server
Multitenancy - I have two ASP.NET MVC 4 domains running on the same website, each with their own databases
We configure our ORM using a static method like so:
public class EndpointConfig: IConfigureThisEndpoint, IWantCustomInitialization {
public void Init() {
var bus = Configure.With()
.AutofacBuilder()
.UnicastBus().LoadMessageHandlers().DoNotAutoSubscribe()
.XmlSerializer()
.MsmqTransport().IsTransactional(true).PurgeOnStartup(false)
.MsmqSubscriptionStorage()
.Sagas().RavenSagaPersister().InstallRavenIfNeeded()
.UseInMemoryTimeoutPersister()
.CreateBus()
.Start();
SlenderConfiguration.Init(bus);
}
}
public class SlenderCofnigruation {
private static ORMScope scope { get; set; }
public static void Init(IBus bus)
{
ORMConfig.GetScope = () =>
{
var environment = "dev";
if (bus.CurrentMessageContext.Headers.ContainsKey("Environment"))
environment = bus.CurrentMessageContext.Headers["Environment"];
if (scope == null)
scope = new SlenderScope(ConfigurationManager.ConnectionStrings[environment].ConnectionString);
return scope;
};
}
}
This works fine in our single-tenant Beta environment - it's fine for that static scope to get re-used because the environment header is always the same for a given deployment.
It's my understanding that this won't work for the multitenant situation described above, because NServiceBus will reuse threads across messages. The same scope would then be used, causing problems if the message was intended for a different environment.
What I think I want is a single scope per message, but I'm really not sure how to get there.
I've seen Unit Of Work Implementation for RavenDB, and the unit of work implementation in the full duplex sample, but I'm not sure that's the right path.
I've also seen the DependencyLifecycle enum, but I'm not sure how I can use that to resolve the scope given the way I have to set up the GetScope func.
Obviously I have no idea what's going on here. Any suggestions?
If you need to do something on a per-message basis, consider using message mutators (IMutateIncomingMessages) in addition to your unit-of-work management with some thread-static state.

Resources