I'm trying to create a CosmosClient instance for use in an ASP.Net MVC application. Microsoft recommends creating a singleton instance of the client. I've figured out I need something in Application_Start in Global.asax but that's it so far. Can anyone please give me an step by step idiots guide on how to do this as I am new to ASP.Net?
I have the following code running in a console app which creates the instance but I don't know how to translate this to an ASP Web App.
public async Task<bool> setupInitialiseClientAsync() // Use to create and also initialise Cosmos client
{
List<(string, string)> containersToInitialize = new List<(string, string)> { (databaseId, containerId) };
this.cosmosClient = await CosmosClient.CreateAndInitializeAsync(PrimaryConnectionString, containersToInitialize);
this.container = cosmosClient.GetContainer(databaseId, containerId);
return true;
}
Thanks.
Related
I would like to use ASP.NET Core's default DI container to setup DI for my Service Fabric project.
//This is what I've got so far, and it works great
ServiceRuntime.RegisterServiceAsync(
"MyServiceType",
context => new MyService(context, new MyMonitor()
).GetAwaiter().GetResult();
//This is how I use it
public MyService(StatefulServiceContext context, IMonitor myMonitor)
: base(context)
{
this._myMonitor = myMonitor;
}
How would I set up DI, if MyMonitor class has a dependency on a ConfigProvider class, like this:
public MyMonitor(IConfigProvider configProvider)
{
this._configProvider = configProvider;
}
I think this question will give you some light: Why does ServiceRuntime.RegisterServiceAsync return before the serviceFactory func completes?
Technically, the ServiceRuntime.RegisterServiceAsync() is a dependency registration, it requires you to pass the serviceTypeName and the factory method responsible for creating the services Func<StatelessServiceContext, StatelessService> serviceFactory
The factory method receives the context and returns a service (Stateful or stateless).
For DI, you should register all dependencies in advance and call resolve services to create the constructor, something like:
var provider = new ServiceCollection()
.AddLogging()
.AddSingleton<IFooService, FooService>()
.AddSingleton<IMonitor, MyMonitor>()
.BuildServiceProvider();
ServiceRuntime.RegisterServiceAsync("MyServiceType",
context => new MyService(context, provider.GetService<IMonitor>());
}).GetAwaiter().GetResult();
PS:
Never Register the context (StatelessServiceContext\StatefulServiceContext) in the DI, in a shared process approach, multiple partitions might be hosted on same process and will have multiple contexts.
This code snippet is not tested, I've used in the past, don't have access to validate if matches the same code, but is very close to the approach used, might need some tweaks.
Hi #OscarCabreraRodrÃguez
I am working on the project that simplifies development of Service Fabric Reliable Services and it has great built-in support for dependency injection scenarios.
You can find general information project page, wiki and specific information about dependency injection here.
The idea is that project abstracts you from working with Service instance directly instead providing you with a set of more concrete objects.
Here is a simple example for ASP.NET Core application:
public static void Main(string[] args)
{
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder
.UseServiceType("ServiceType")
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder
.UseEndpoint("ServiceEndpoint")
.UseUniqueServiceUrlIntegration()
.ConfigureWebHost(
webHostBuilder =>
{
webHostBuilder
.ConfigureServices(
services =>
{
// You can configure as usual.
services.AddTransient<IMyService, MyService>();
})
.UseStartup<Startup>();
});
});
})
.Build()
.Run();
[Route("api")]
public class ApiController : Controller
{
public ApiController(IMyService service) { }
[HttpGet]
[Route("value")]
public string GetValue()
{
return $"Value from {nameof(ApiController)}";
}
}
Hope I understand your use case correctly and this information is relevant.
I'm using ASP.Net Identity and in my Web Api project in its AccountController I want to send verification email to new users. I have plugged my email service using MVCMailer to the ASP.Net identity.
public class EmailService : IIdentityMessageService
{
private readonly IUserMailer _userMailer;
public EmailService(IUserMailer userMailer)
{
_userMailer = userMailer;
}
public Task SendAsync(IdentityMessage message)
{
_userMailer.DeliverMessage(message.Body);
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
}
#
public class UserMailer : MailerBase, IUserMailer
{
public UserMailer()
{
MasterName = "_Layout";
}
public virtual IMailMessage DeliverMessage(string message)
{
var mailMessage = new MailMessage();
mailMessage.To.Add("hashemp206#yahoo.com");
mailMessage.Subject = "Welcome";
//ViewData = new System.Web.Mvc.ViewDataDictionary(model);
PopulateBody(mailMessage, "Welcome");
mailMessage.Send();
return mailMessage;
}
my custom ASP.Net Identiy is in a seperate project. and as you see above EmailService is dependent on IUserMailer interface. and IUserMailer implementation is in another project MyProject.MVCMailer (this project is an MVC project)
in my dependency resolver in web api I try to resolve this dependency
container.Bind<IUserMailer>().To<UserMailer>().InSingletonScope();
but MVCMailer has a dependency to System.Web.MVC and ninject complain for this reference to initialize USerMailer.
so the problem is here I dont want to add System.Web.MVC to my Web Api project.
how can I use MVCMailer without referencing to System.Web.MVC in my web api project?
I'm a little confused on what you're trying to do but if I'm understanding you correctly you are trying to call your API and then send out an email. Since you are not passing anything from the API into the email (and even if you were) just call your API and return a response object. Once the MVC project recieves the response send the email from the MVC project. Your API should know about objects in your MVC project unless there is a really good reason. Think of them (your MVC and API projects) as two separate entities all together that don't know about each other.
thanks in advance for any help. I changed to mvc4 and start using app_start/routeconfig.cs to register routes.
Probably it dont have any relation with autofac but I cannot find a solution, does anyone know if its neccesary to declare routetable.routes in any additional place - I already declared RouteConfig.RegisterRoutes(RouteTable.Routes); in global.asax - when planning to use autofac with mvc4 razor´s internet template?.
Currently no map.route definition is working in my app. I dont know if I have to declare an instance like
RegisterInstance(RouteTable.Routes);
thank you so much.
This is basically the minimum amount of code to configure Autofac for mvc. You will need to reference Autofac.Integration.Mvc, and if you're using webapi you need to reference Autofac.Integration.Webapi too.
public static class AutofacConfig
{
public static IContainer Register()
{
var assembly = typeof(MvcApplication).Assembly;
var builder = new ContainerBuilder();
builder.RegisterControllers(assembly);
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
builder.RegisterApiControllers(assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
return container;
}
}
In Global.Asax you can then add
AutofacConfig.Register();
in the Application_Start method as one of the first calls.
I've set up a Web API project using Ninject, and I've used the fix detailed here for getting it to work with the latest version of the Web API. Everything is working fine, but I'm now trying to write some tests.
I'm using in-memory hosting to run the project for the tests, as detailed here, as I have a DelegatingHandler that performs authentication and then sets a property on the request message that is used by all the Api Controllers.
So, I've got a base class for my tests, and have a SetUp method where I set up the HttpServer and configuration, which I've pretty much taken from my working Ninject code:
[SetUp]
public void Setup()
{
bootstrapper = new Bootstrapper();
DynamicModuleUtility.RegisterModule(
typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(
typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("Login",
"api/auth/token",
new { controller = "Users", action = "Login" });
config.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always;
config.DependencyResolver =
new NinjectResolver(CreateKernel());
config.MessageHandlers.Add(
new AuthenticationHandler(CreateUserManager()));
Server = new HttpServer(config);
}
This is how I create the MoqMockingKernel:
private static IKernel CreateKernel()
{
var kernel = new MoqMockingKernel();
kernel.Bind<Func<IKernel>>()
.ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>()
.To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver =
new NinjectResolver(kernel);
return kernel;
}
And this is how I register the objects to use:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserManager>().ToMock();
kernel.Bind<UsersController>().ToSelf();
}
While I'm not testing the Controller per se, I do want a proper instance of it to be called, which is why I'm binding it ToSelf. I must admit that I am assuming that this is correct. This is an example of a test:
public void UserCannotLogin()
{
System.Net.Http.HttpClient client =
new System.Net.Http.HttpClient(Server);
string json = string.Format(
"{{ \"Username\": \"{0}\", \"Password\": \"{1}\" }}",
"wrong", "wrong");
HttpRequestMessage request =
CreateRequest(#"api/auth/token", json, HttpMethod.Get);
Action action = () => client.SendAsync(request);
using (var response = client.SendAsync(request).Result)
{
response.StatusCode.Should()
.Be(HttpStatusCode.Unauthorized);
}
}
I'm basically getting a 404 error. When I debug it, it does go to my DelegatingHandler, but it doesn't go to my controller.
I get the feeling that I'm fundamentally missing a point here, and it may not even be possible to do what I'm trying to do, but if anyone has any suggestions for either how to do this, or a different way to achieve the same thing, I'm all ears.
Update I think that it's because the default behaviour of the MockingKernel is to provide a Mock unless told otherwise, so it is returning a Mock of IHttpControllerSelector. I've set up a couple of default ones now:
kernel.Bind<IHttpControllerSelector>()
.To<DefaultHttpControllerSelector>();
kernel.Bind<IContentNegotiator>()
.To<DefaultContentNegotiator>();
It's still not working, I think because there are no formatters specified. I'll try that tomorrow and see if that gets me there.
Ok, I think that I was correct when I said that I was fundamentally missing a point here, but I'll answer this in case it helps someone else avoid the same mistake!
The Ninject MockingKernel is, I think, primarily about auto-mocking, so where you have a lot of interfaces you don't care about how they are set up in your test, you can ignore them in your tests and they will be automatically created for you.
In the case of the Web API, this is most definitely not the case, as you don't want the controller selector class to be auto mocked, otherwise you won't end up calling your controllers.
So, the solution I've come up with is to stick with using a standard Ninject Kernel, and then bind your interface to a constant Mock object:
kernel.Bind<IUserManager>().ToConstant(CreateUserManager());
private IUserManager CreateUserManager()
{
Mock<IUserManager> userManager = new Mock<IUserManager>();
// Set up the methods you want mocked
return userManager.Object;
}
Doing this, I've been able to successfully write tests that use an HttpClient to call an in-memory HttpServer that successfully call my DelegatingHandler and then end up at my controllers.
after a lot of googling and reading several solutions on how to manage mixed mode authentication in ASP.NET apps, I still have no fitting solution for my problem.
I've got to implement an intranet application for a bunch of different user groups. Until now i've used windows authenthication which was very simple to implement. My problems arise when it comes to authorizing usergroups for special application functionalities.
Using [Authorize(Users = "DOMAIN\\USER")] works great but due to that i have no access to the active directory managament, it is impossible to me to configure rolemanagement in the way I need it for my application.
What I'd like to do is defining custom roles and memberships in addition to the ones that are defined within the active directory (is such an extension possible? e.g. by implementing an own membershipprovider?).
What do you think is the best solution for my problem. Do I really have to implement a complex mixed mode authentication with forms authentication in addition to windows authentication?
Used Technologies:
MS SQL Server 2008
MS VS 2010
ASP.NET MVC 3 - Razor View Engine
Telerik Extensions for ASP.NET MVC
IIS 7 on Windows Server 2008
EDIT (final solution thanks to the help of dougajmcdonald):
After pointing me to use a custom IPrincipal implementation I've found some solutions here and here. Putting everything together I came to the following solution:
1.Create a custom principal implementation:
public class MyPrincipal: WindowsPrincipal
{
List<string> _roles;
public MyPrincipal(WindowsIdentity identity) : base(identity) {
// fill roles with a sample string just to test if it works
_roles = new List<string>{"someTestRole"};
// TODO: Get roles for the identity out of a custom DB table
}
public override bool IsInRole(string role)
{
if (base.IsInRole(role) || _roles.Contains(role))
{
return true;
}
else
{
return false;
}
}
}
2.Integrate my custom principal implementation into the application through extending the "Global.asax.cs" file:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
WindowsIdentity wi = (WindowsIdentity)HttpContext.Current.User.Identity;
MyPrincipal mp = new MyPrincipal(wi);
HttpContext.Current.User = mp;
}
}
3.Use my custom roles for authorization in my application
public class HomeController : Controller
{
[Authorize(Roles= "someTestRole")]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
It works!!! yeah!
I'm not sure if this still applies in MVC, but in Webforms one way to do this would be as follows:
Create a new IPrincipal implementation perhaps extending WindowsPrincipal
In this class, give it a collection of roles (your own custom roles)
Populate those roles, by perhaps getting them from the DB.
Override IsInRole to return true if the role provided is EITHER true from the base call (WindowsAuthentication/Role) OR from your own custom role collection.
This way you can still hook into Principal.IsInRole("MyRole") and also the principal [PrincipalPermission()] annotation.
Hope it helps.
EDIT in answer to q's:
To integrate the principal into the authorisation you need to write your own method for OnAuthenticate in the global.asax for the type of authentication, so I would guess for you, something like this:
void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
{
// ensure we have a name and made it through authentication
if (e.Identity != null && e.Identity.IsAuthenticated)
{
//create your principal, pass in the identity so you know what permissions are tied to
MyCustomePrincipal opPrincipal = new MyCustomePrincipal(e.Identity);
//assign your principal to the HttpContext.Current.User, or perhaps Thread.Current
HttpContext.Current.User = opPrincipal;
}
}
I believe Authorize came in at a later date to the PrincipalPermission, but I'm not too sure as to when/why of the differences I'm afraid :( - sorry!