Error calling ServiceStack service with mvc4 Controller - c#

I'm trying to figure out how to call a service from an asp mvc4 controller, but I just can't. I already set up the services but when I'm trying to call from my controller method it displays this :
http://s10.postimg.org/5ojcryn7t/error_1.png
Here's my code:
Global.asax.cs
namespace mvc4_servicestack
{
// Nota: para obtener instrucciones sobre cómo habilitar el modo clásico de IIS6 o IIS7,
// visite http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public class AppHost : AppHostBase
{
public AppHost()
: base("Nombre del Host de los WebService", typeof(SS_WebServices.StatusService).Assembly)
{ }
public override void Configure(Funq.Container container)
{
}
}
protected void Application_Start()
{
new AppHost().Init();
AreaRegistration.RegisterAllAreas();
// WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
}
SS_WebServices.cs
namespace mvc4_servicestack
{
public class SS_WebServices
{
//Request DTO Objet
[ServiceStack.ServiceHost.Route("/Home/About/statuss")]
[ServiceStack.ServiceHost.Route("/Home/About/statuss/{Name}")]
public class StatusQuery : ServiceStack.ServiceHost.IReturn<StatusResponse>
{
public string Name { get; set; }
public int Id { get; set; }
}
//Response DTO Object
public class StatusResponse
{
public string Result { get; set; }
}
//Service
public class StatusService : ServiceStack.ServiceInterface.Service
{
//Implement teh Method VERB (POST,GET,PUT,DELETE) OR Any for ALL VERBS
public object Any(StatusQuery request)
{
//Looks strange when the name is null so we replace with a generic name.
var name = request.Name ?? "John Doe";
return new StatusResponse { Result = "Hello, " + name };
}
}
}
}
I've been reading the post Should ServiceStack be the service layer in an MVC application or should it call the service layer?
But Still I can't understand things like :
WHY Register returns an Interface instead a GreeterResponse? container.Register(c => new Greeter());
I really hope you guys can help me...!

Since ServiceStack is hosted in the same AppDomain as MVC, you don't need to use a ServiceClient and go through HTTP to access ServiceStack Services, instead you can just resolve and call the Service normally, E.g:
public HelloController : ServiceStackController
{
public void Index(string name)
{
using (var svc = base.ResolveService<HelloService>())
{
ViewBag.GreetResult = svc.Get(name).Result;
return View();
}
}
}
Outside of a Controller a ServiceStack Service can be resolved via HostContext.ResolveService<T>()
See the MVC Integration docs for more info.
But Still I can't understand things like : WHY Register returns an Interface instead a GreeterResponse? container.Register(c => new Greeter());
Greeter is just a normal C# dependency (i.e. it's not a ServiceStack Service). The container isn't returning IGreeter here, instead it's saying to "Register the Greeter implemenation against the IGreeter interface":
container.Register<IGreeter>(c => new Greeter());
If you registered it without, it will just be registered against the concrete type, e.g. these are both equivalent:
container.Register(c => new Greeter());
container.Register<Greeter>(c => new Greeter());
Which means you would need to specify the concrete dependency to get it auto-wired, e.g:
public class MyService : Service
{
public Greeter Greeter { get; set; }
}
Instead of being able to use:
public IGreeter Greeter { get; set; }
Which is much easier to test given that it's a mockable interface.

Related

C# Injecting Specific Item from appSettings.json at runtime

How can I inject a specific setting (of possibly many) from an array appSettings.json in a C# .NET Core Web API, based on a runtime input value?
appSettings.json:
{
"SettingProfiles": [
{
"Name": "Profile1",
"SettingA": "SettingAValue1",
"SettingB": "SettingBValue1"
},
{
"Name": "Profile2",
"SettingA": "SettingAValue2",
"SettingB": "SettingBValue2"
}
...
}
Settings Classes:
public class Settings {
public List<SettingsProfile> SettingsProfiles { get; set; }
}
public class SettingsProfile {
public string Name { get; set; };
public string SettingA { get; set; };
public string SettingB { get; set; };
}
Service class:
public class MyService : IMyService {
private readonly SettingsProfile _Profile;
public MyService(SettingsProfile profile) {
_Profile = profile;
}
public void DoStuff() {
Console.WriteLine($"Setting A: {_SettingsProfile.SettingA}, Setting B: {_SettingsProfile.SettingB}")
}
}
The user will enter the setting name they want to apply. I am unsure how to do this if the service is configured in Startup.cs, at which point I don't yet have the setting to use.
I am understanding that "newing" the service would be bad practice, although that's the only way I can figure out how to make it work:
public class MyController {
private readonly Settings _Settings;
public MyController(Settings settings) {
_Settings = settings;
}
public IActionResult DoStuff(profileName) {
SettingsProfile profile = _Settings.Where(profile => profile.Name == profileName);
MyService service = new Service(profile);
}
}
I'm obviously missing something, but I've been watching YouTube videos on Dependency Injections and reading StackOverflow until my eyes bleed, and haven't figured it out yet. Can someone help me with a pattern that I should be following?
This is how I think it should work.
It will be a lot cleaner if you use another pattern: Factory.
interface ISettingServiceFactory{
MyService GetService(string profileName);
}
class SettingServiceFactory: ISettingServiceFactory
{
MyService GetService(string profileName){
}
}
Now you can implement GetService in two ways.
The first one is by creating new as you did in the controller and is not that bad as this is the purpose of the factory. In this way you kind of move that logic somewhere else.
A second one would be a bit uglier but something like this
interface ISettingServiceFactory{
MyService GetService(string profileName);
void SetCurrentProfile(SettingsProfile profile);
}
class SettingServiceFactory: ISettingServiceFactory
{
private IServiceProvider _serviceProvider;
private Settings _Settings;
public SettingServiceFactory(IServiceProvider serviceProvider,Settings settings){
_serviceProvider = serviceProvider;
_Settings = settings;
}
MyService GetService(string profileName){
var service = _serviceProvider.GetRequiredService<MyService>();
var profile = _Settings.Where(profile => profile.Name == profileName);
service.SetCurrentProfile(profile);
return service;
}
}
This second approach would be useful only if the implementation of MyService has a lot of other dependencies by itself and if you want to avoid new at any cost.
In both cases you will inject the factory in the controller
public MyController(ISettingServiceFactory settingServiceFactory) {
_settingServiceFactory= settingServiceFactory;
}
public IActionResult DoStuff(profileName) {
MyService service = _settingServiceFactory.GetService(profileName)
}

ASP.NET Core MVC inject per request

I am looking forward to inject RequestContext, per request in .Net Core. inside the service collection.
Someone attempted 8 yrs. ago.
ASP.NET MVC inject per request
public interface IMvcDepency
{
string PathValue { get; set; }
}
public class FakeMvcDepency : IMvcDepency
{
public string PathValue { get; set; }
}
public class MvcDepency : IMvcDepency
{
public string PathValue { get; set; }
public MvcDepency(HttpRequest req)
{
PathValue = req.Path.Value;
}
}
And inject it somewhere in startup, as follows:
services.AddTransient<IMvcDepency, MvcDepency>(x => x.???);
or in OnActionExecuting like below:
public override void OnActionExecuting(ActionExecutingContext actCtx)
{
MvcDepency mvcDepency = actCtx.HttpContext.RequestServices.GetService(typeof(IMvcDepency)) as MvcDepency;
mvcDepency = new MvcDepency(actCtx.HttpContext.Request);
actCtx.HttpContext.RequestServices.AddService(mvcDepency);// AddService method doesn't in exist
}
Current Error:
System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpRequest' while attempting to activate 'CAWP.Api.Controllers.MvcDepency'.'
Controllers already have access to the HttpRequest object in each of the methods via the base class. But it is only available once a method is called (for obvious reasons!). If you want to wrap it in your own class then you can do it in the OnActionExecuting override.
You can create a new MvcDepency class in OnActionExecuting and reference it in the code. As controllers are created per request you should be able to use a class variable to store the reference.
public class ValuesController : Controller
{
private IMvcDepency _depency;
public ValuesController()
{
}
public override void OnActionExecuting(ActionExecutingContext context)
{
_depency = new MvcDepency(context.HttpContext.Request);
base.OnActionExecuting(context);
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
var path = _depency.PathValue;
return new string[] { "PathValue", path };
}
}
This should result in the MvcDepency class having access to the HttpRequest object.
You should add a factory class for your IMvcDepency interface to avoid the new in OnActionExecuting.

How to inject WCF service client in ASP.Net core?

I have WCF service that I need to access from ASP.NET Core. I have installed WCF Connected Preview and created proxy successfully.
It created interface & client something like below
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.3.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IDocumentIntegration")]
public interface IDocumentIntegration
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDocumentIntegration/SubmitDocument", ReplyAction="http://tempuri.org/IDocumentIntegration/SubmitDocumentResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(ServiceReference1.FaultDetail), Action="http://tempuri.org/IDocumentIntegration/SubmitDocumentFaultDetailFault", Name="FaultDetail", Namespace="http://schemas.datacontract.org/2004/07/MyCompany.Framework.Wcf")]
System.Threading.Tasks.Task<string> SubmitDocumentAsync(string documentXml);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.3.0.0")]
public interface IDocumentIntegrationChannel : ServiceReference1.IDocumentIntegration, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.3.0.0")]
public partial class DocumentIntegrationClient : System.ServiceModel.ClientBase<ServiceReference1.IDocumentIntegration>, ServiceReference1.IDocumentIntegration
{
// constructors and methods here
}
The consumer class that calls the service looks like below
public class Consumer
{
private IDocumentIntegration _client;
public Consumer(IDocumentIntegration client)
{
_client = client;
}
public async Task Process(string id)
{
await _client.SubmitDocumentAsync(id);
}
}
How do I register the IDocumentIntegration with ConfigureServices method in Startup class?
I want to setup RemoteAddress & clientCredentials during the registration
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc();
// how do I inject DocumentIntegrationClient here??
var client = new DocumentIntegrationClient();
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "password";
client.Endpoint.Address = new EndpointAddress(urlbasedonenvironment)
}
Using the factory method overload seems suitable use case for it.
services.AddScoped<IDocumentIntegration>(provider => {
var client = new DocumentIntegrationClient();
// Use configuration object to read it from appconfig.json
client.ClientCredentials.UserName.UserName = Configuration["MyService:Username"];
client.ClientCredentials.UserName.Password = Configuration["MyService:Password"];
client.Endpoint.Address = new EndpointAddress(Configuration["MyService:BaseUrl"]);
return client;
});
Where your appsettings would look like
{
...
"MyService" :
{
"Username": "guest",
"Password": "guest",
"BaseUrl": "http://www.example.com/"
}
}
Alternatively, inject the Options via options pattern. Since the DocumentIntegrationClient is partial, you can create a new file and add a parameterized constructor.
public partial class DocumentIntegrationClient :
System.ServiceModel.ClientBase<ServiceReference1.IDocumentIntegration>, ServiceReference1.IDocumentIntegration
{
public DocumentIntegrationClient(IOptions<DocumentServiceOptions> options) : base()
{
if(options==null)
{
throw new ArgumentNullException(nameof(options));
}
this.ClientCredentials.Username.Username = options.Username;
this.ClientCredentials.Username.Password = options.Password;
this.Endpoint.Address = new EndpointAddress(options.BaseUrl);
}
}
And create a options class
public class DocumentServiceOptions
{
public string Username { get; set; }
public string Password { get; set; }
public string BaseUrl { get; set; }
}
and populate it from appsettings.json.
services.Configure<DocumentServiceOptions>(Configuration.GetSection("MyService"));

instantiates class using ninject ioc in .net

I am using Ninject to do some IoC in my ASP.NET MVC application.
I have an interface "IService.cs" :
public interface IService
{
string method();
}
I have the corresponding implementation "Service.cs" :
public class Service
{
string method()
{
return "result";
}
}
I have done the binding in another class heriting from NinjectModule :
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
RegisterServices();
}
private void RegisterServices()
{
Kernel.Bind<IService>().To<Service>();
}
}
I have my class A which use this service :
public class A
{
private readonly IService _service;
private int i;
public A(IService service, int i)
{
this._service=service;
this.i=i;
}
}
The problem is that now, I don't know how to instantiate my class A in my application. This is where am I stuck, how can I call Ninject
to tell my app to go get the implementation of my interface:
var myClass=new A(????)
The main problem is that your Service class does not implement IService.
public class Service
{
string method()
{
return "result";
}
}
It should be
public class Service : IService
{
public string method()
{
return "result";
}
}
But as for instantiating a class, the best approach is to use a composition root to build an object graph. In MVC, that is best handled by implementing IControllerFactory.
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public NinjectControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)this.kernel.Get(controllerType);
}
}
Usage
using System;
using Ninject;
using DI;
using DI.Ninject;
using DI.Ninject.Modules;
internal class CompositionRoot
{
public static void Compose()
{
// Create the DI container
var container = new StandardKernel();
// Setup configuration of DI
container.Load(new MyNinjectModule());
// Register our ControllerFactory with MVC
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(container));
}
}
In Application_Start, add:
CompositionRoot.Compose();
You will also need to create an interface for your class A and register it. An integer cannot be resolved automatically, you have to do that explicitly.
Kernel.Bind<IClassA>().To<A>()
.WithConstructorArgument("i", 12345);
And then you would add your dependency to a controller. Dependencies of dependencies are resolved automatically.
public class HomeController : Controller
{
private readonly IClassA classA;
public HomeController(IClassA classA)
{
if (classA == null)
throw new ArgumentNullException("classA");
this.classA = classA;
}
public ActionResult Index()
{
// Use this.classA here...
// IService will be automatically injected to it.
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
}

Is it possible to resolve a URL in an injected class constructor using Ninject?

I have a service class that is being used in an ASP.Net MVC 5 web application and in a console application also. Let's call it MyService. When a MyService object is being instantiated by Ninject to be passed to a controller in a web context, I would like a URL to be resolved using something like this
url = Request.Url.GetLeftPart(UriPartial.Authority) + Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Emailer" });
When MyService is being instantiated by my console app (using Ninject also, but in a non-web context), I would like it to take the url from AppSettings like this:
url = ConfigurationManager.AppSettings["EmailerUrl"];
Is this feasible? I think it might be using WithConstructorArgument() with the proper arguments in NinjectWebCommon.RegisterServices(IKernel kernel) when creating the binding, but I don't know how exactly.
My guess is that the MyService constructor would have to know about the controller class in which it is being injected and be able to call methods from that controller. If no controller class is known, then it would use the app settings.
Of course, I could also set the url parameter within each controller constructor being passed a MyService object, and elsewhere in the console app, but I would prefer not to worry about setting this attribute every time a MyService object is instantiated.
So let's start with:
public interface IUrl
{
Url Url { get; }
}
internal class ControllerBasedUrl : IUrl
{
public ControllerBasedUrl(string controllerName)
{
this.Url = null; // implement
}
public Url Url { get; private set; }
}
internal class AppConfigBasedUrl : IUrl
{
public AppConfigBasedUrl()
{
this.Url = null; // implement
}
public Url Url { get; private set; }
}
There's multiple approaches you can use:
a) make it known to the application whether you're running in a web application or console application, and then use a conditional binding:
var kernel = new StandardKernel();
if (runningInConsoleApplication)
{
kernel.Bind<IUrl>().To<AppConfigBasedUrl>();
}
else
{
kernel.Bind<IUrl>().ToMethod(ctx =>
{
IRequest controllerRequest = ctx.Request.TraverseRequestChainAndFindMatch(x => x.Target.Name.EndsWith("Controller"));
return new ControllerBasedUrl(controllerRequest.Target.Type.Name);
});
}
b) make the binding for url conditional on whether it is injected into controller or not:
var kernel = new StandardKernel();
kernel.Bind<IUrl>().ToMethod(ctx =>
{
IRequest controllerRequest = ctx.Request.TraverseRequestChainAndFindMatch(x => x.Target.Name.EndsWith("Controller"));
if (controllerRequest != null)
{
return new ControllerBasedUrl(controllerRequest.Target.Type.Name);
}
return new AppConfigBasedUrl();
});
both using this extension:
public static class RequestExtensions
{
public static IRequest TraverseRequestChainAndFindMatch(this IRequest request, Func<IRequest, bool> matcher)
{
if (matcher(request))
{
return request;
}
if (request.ParentRequest != null)
{
return request.ParentRequest.TraverseRequestChainAndFindMatch(matcher);
}
return null;
}
}

Categories

Resources