OWIN Startup class not auto-detected despite having Startup.cs in matching assembly name and global assembly name - asp.net-web-api

I created a web API and added the OWIN middleware to the project, i.e. Startup.cs, the Startup.Auth.cs, and OpenIdConnectCachingSecurityTokenProvider.cs (as needed for Azure AD B2C).
However, my Web API requires that I use the assembly attribute [assembly: OwinStartup(typeof(My_Web_API_2.Startup))] in Startup.cs, otherwise the OWIN startup class isn't detected. The TaskService app in the Azure AD B2C sample doesn't require the attribute to work.
The OWIN Startup class detection docs state that
Naming Convention: Katana looks for a class named Startup in
namespace matching the assembly name or the global namespace.
But my web API is using a matching assembly name and global namespace? What am I missing from my web API to detect the OWIN Startup class?

The assembly name has -'s but the namespace has _'s.
This probably happened when you performed a File -> New Project. VS converted the hyphens to underscores in the namespace for you (and didn't tell you!).

Related

How to identify the right assembly to reference when abstracting logic to class libraries and choose between referencing an assembly or NuGet package

I am attempting to abstract some of our common WebApi bootstrapping logic into projects that all WebApis can reference. The general idea being that all the builder.Services.Blah() and app.UseOtherBlah() calls are standardised across our projects.
My assumption was that I would just create a class library and reference any assemblies I needed.
But I'm running into confusions due to the class library obviously not being a Web API project that's been all nicely set up for the web bootstrapping process.
The code below exists in a class library project as the only class. It is my attempt to abstract out the logging configuration. It doesn't do anything useful at the moment as I am just proofing the concept of abstracting this out into a class library.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace XXXX.Hosting
{
public static class ExtendILoggingBuilder
{
public static ILoggingBuilder ConfigureLoggingProviders(this ILoggingBuilder logging, ConfigurationManager configuration)
{
// TODO: load providers from config
logging.ClearProviders();
logging.AddConsole();
return logging;
}
}
}
I need references (of some kind) to Microsoft.Extensions.Configuration and Microsoft.Extensions.Logging.
VS offers me the choice for Microsoft.Extensions.Logging between an assembly and a NuGet package.
But for Microsoft.Extensions.Configuration, I only get offered a NuGet package.
When I install the package, the dlls inside are not the dlls listed in the documentation page for the ConfigurationManager class here.
And I can't find the dll listed anywhere on my disk. Nor is it offered via NuGet.
My question is:
How do I work out a) what dll I need and b) where to get it from?
I don't really want a mixture of NuGet package references and assembly references. And I don't really want to reference anything I don't need to reference.

Web Service can not find in MainActivity.cs in xamarin android OR how to call web service from mainactivity in xamarin android

I am Trying to call a web service in Xamarin Android Project. But when adding service reference in my project and trying to create reference of that web service it says 'HelloService' is a namespace but is used like a type.
MainActivity.cs
Solution Structure:
This is not an issue with xamarin.android, it's an issue with naming, i assume you have something like this.
namespace HelloService
{
class HelloService
{
}
Don't use same name for classes and namespace, more detail here

Xamarin Unit Testing Portable Bait and Switch error with Xamarin.Auth?

I have set up a TestProject in Visual Studio for Mac that references my Xamarin Forms project for testing the non-visual portions of my code.
However I am getting the following error when I try to test a piece of my code that leverages Xamarin.Auth to access the keychain.
System.NotImplementedException :
Portable Bait And Switch is nuget feature, so the package must be installed in all project.
NotImplementedException will indicate that Portable Code from PCL is used and not Platform Specific
implementation. Please check whether platform specific Assembly is properly installed.
Cannot save account in Portable profile - bait-and-switch error.
Please file a bug in https://bugzilla.xamarin.com
This code works fine running on the iOS simulator, and I assume it has something to do with the way xamarin auth leverages the ios Keychain which is not present in this test project. I tried to add my ios solution in references, but I am unable to do so in "edit references" of my test project. The project references dialog wont permit it:
Here is the code that is failing in my PCL.
AccountStore store;
store = AccountStore.Create();
Apparently it has trouble with AccountStore.Create()
Here is the testcode class that calls the PCL:
using System;
using NUnit.Framework;
using CrowdWisdom;
using CrowdWisdom.Authentication;
namespace CrowdWisdomTest
{
[TestFixture()]
public class AuthServiceTest
{
[Test()]
public void SaveRestoreSecret()
{
String secret = "ABCD";
AuthService auth = AuthService.GetInstance();
auth.putSecret("MySecret", secret);
Assert.AreEqual(secret, auth.GetSecret("MySecret"));
}
}
}
Bait And Switch pattern that most cross-platform plugins use - is not a very unit-test friendly pattern. As you can see in your example.
My very first recommendation would be to use a contract based approach, alongwith with a dependency-injection container for your authorization process; so that you can provide a mock implementation as unit-test context. But if that is not possible, then you can use following hack to provide your own mock-switch for these static classes.
Basically, the error you see is because your portable code is accessing the portable version of Xamarin.Auth which is just intended to be the bait. So you will have to create your own implementation to act as switch in unit-test context (as they have done in platform specific libraries in Xamarin.Auth).
In order to do that, you will need to:
Create another portable library (which will only be used by your unit-test project). Let's say we name it Xamarin.Auth.Mocks. Make sure to update the root namespace, and assembly name as 'Xamarin.Auth' in its properties page.
Add a mock account store class and implement AccountStore using switch pattern.
namespace Xamarin.Auth
{
/// <summary>
/// A persistent storage for <see cref="Account"/>s. This storage is encrypted.
/// Accounts are stored using a service ID and the username of the account
/// as a primary key.
/// </summary>
#if XAMARIN_AUTH_INTERNAL
internal abstract partial class AccountStore
#else
public abstract partial class AccountStore
#endif
{
public static AccountStore Create()
{
return new MockAccountStore();
}
}
public class MockAccountStore : AccountStore
{
}
}
Add reference to Xamarin.Auth.Mocks in your unit-test library
Now every time you run your unit-tests, your portable code, will find your mock switch implementation for all their Xamarin.Auth needs, and you achieve true isolation from Xamarin.Auth; which technically is something we aspire to anyways when we write unit-test(s).
Note: If your portable code uses other bait-switch classes, add mock implementation for them too in your Xamarin.Auth.Mocks library. You only need to add mock classes for the ones that you use in your code; not all of the classes in Xamarin.Auth
I had the same issue, in my case the Xamarin.Auth version was the same (1.7.0) in all projects.
I solved the issue by editing the .csproj in this way:
<Reference Include="Xamarin.Auth, Version=1.6.0.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xamarin.Auth.1.7.0\lib\MonoAndroid10\Xamarin.Auth.dll</HintPath>
<Private>True</Private>
</Reference>
Adding the tag <Private>True</Private> solved the issue for me.
The reference must be present and with this tag in .csproj files.

WebApi Map Router

I am using WebApi in our project. We have same controller name defined under different sub-folder. Like:
Controllers
|----Admin
| |----MyProjectsController.cs
|
|----User
|----MyProjectsController.cs
How can we define a route config for such scenario.
/api/admin/MyProjects
/api/user/MyProjects
Thanks.
This is not directly supported by route templates because the namespace is not considered when using Web API controllers. You need to use Web API routing attributes. And you have to manually specify them (they now nothing about the folder or namespace in which the Controller is included).
Particularly you should have a look at Route prefixes. For example:
[RoutePrefix("Admin")]
public class MyProjectController: ApiController

Http.EnumRouteContraint must implement System.Web.Routing.IRouteConstraint

I'm using AttributeRouting in my Web API project. I've installed the AttributeRouting for Web API. I want to define an Enum route constraint so I setup my AttributeRoutingHttpConfig config as follows:
using System.Reflection;
using System.Web.Http;
using AttributeRouting.Web.Http.Constraints;
using AttributeRouting.Web.Http.WebHost;
using MyProject.Data.Models;
[assembly: WebActivator.PreApplicationStartMethod(typeof(PhantasyTour.AttributeRoutingHttpConfig), "Start")]
namespace MyProject
{
public static class AttributeRoutingHttpConfig
{
public static void RegisterRoutes(HttpRouteCollection routes)
{
routes.MapHttpAttributeRoutes(
config =>
{
config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
config.InlineRouteConstraints.Add("ListType", typeof(EnumRouteConstraint<ListType>));
});
}
public static void Start()
{
RegisterRoutes(GlobalConfiguration.Configuration.Routes);
}
}
}
When I fire up my application I immediately receive the following error:
The constraint "AttributeRouting.Web.Http.Constraints.EnumRouteConstraint`1[[MyProject.Data.Models.ListType, MyProject.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" must implement System.Web.Routing.IRouteConstraint
I've looked at the source code for the AttributeRouting.Web.Http.Constraints.EnumRouteConstraint and confirmed that it implements IHttpRouteConstraint which presumably is the WebAPI equivalent of IRouteConstraint in the MVC namespace.
Does anyone know what I'm doing wrong and how I can get this working?
UPDATE:
I attempted to create a completely blank Web Application and add only WebAPI and AttributeRouting for WebAPI references. Despite having absolutely no references to MVC assemblies, I still receive the same error message. I did discover however that there is another EnumRouteConstraint found in the AttributeRouting.Web.Constraints namespace which works perfectly. It doesn't appear to be MVC specific since it is located in the Core AttributeRouting assembly. I would love to know why there are two different EnumRouteConstraint classes when only one of them works. But that is a question for another time.
It is interesting that the exception you get refers to the MVC interface from the namespace System.Web.Routing.
I would take it as a clue and look at all the references in your project, any place in the config where MVC Routes and Http Routes could have been mixed up.
If possible and if you have any at all, try removing all references to MVC (or System.Web.Routing for a start), and MVC flavour of attribute routing (if it's a separate dll).

Resources