WebApi controller tests method not found - c#

I have a very simple WebAPI 2 controller running on .NET Framework 4.6.2, that looks like this:
[RoutePrefix("Invitations")]
public class InvitationsController : CqrsApiController
{
[HttpPost, Route("Clients/{id:long}/Actions/Cancel")]
public IHttpActionResult PostClientInvitationCancel(long id, [FromBody] ClientInvitationCancelCommand command)
{
Execute(command);
return SeeOther("Invitations/Clients/{0}", id);
}
}
and am trying to write an NUnit test for it, like this:
[TestFixture]
public class WhenExecutingAValidCommand
{
[Test]
public void ItShouldReturnARedirect()
{
var dispatcher = Substitute.For<ICqrsDispatcher>();
var urlHelper = Substitute.For<UrlHelper>();
urlHelper.Link(Arg.Any<string>(), Arg.Any<object>()).Returns("https://tempuri.org/");
var sut = new InvitationsController(dispatcher);
sut.Request = new HttpRequestMessage();
sut.Configuration = new HttpConfiguration();
sut.Url = urlHelper;
var response = sut.PostClientInvitationCancel(1, new ClientInvitationCancelCommand());
response.Should().BeOfType<SeeOtherRedirectResult>();
}
}
```
However, when I run the test, I get the following error:
System.MissingMethodException : Method not found: 'Void System.Web.Http.ApiController.set_Request(System.Net.Http.HttpRequestMessage)'.
at ApiProjectTests.InvitationsControllerTests.WhenExecutingAValidCommand.ItShouldReturnARedirect()
The same code seems to work fine in similar projects based on .NET Framework 4.5.1, so I'm wondering if there's some sort of DLL hell going on here. System.Web.Http is using Microsoft.AspNet.WebApi.Core.5.2.3, whereas System.Net.Http is coming from the GAC (well, C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Net.Http.dll to be more precise).
Update: if I try to debug into the unit test, the error occurs before I even enter the method. So although VS2017 compiles the tests just fine, when the test runner fires up, then everything falls apart. Sounds more like DLL hell to me.
Update 2: if I comment out the setting of the request, then I can debug into the test method. If I then put in a breakpoint, and then use the Immediate window to directly set the request property, it works, and there is no Method not found error. I also disabled Resharper and used VS2017's Test Explorer to run the tests, in case R# was caching something, but it made no difference.

It looks like my problem is indeed DLL hell, more specifically the DLL hell referenced by https://github.com/dotnet/corefx/issues/25773. The issue is caused by other NuGet packages that contain references to the newer version of System.Net.Http (4.2.0.0). The current solution appears to be to add a binding redirect to downgrade the assembly version to the expected version (4.0.0.0), but so far that has not helped me.
The solution that did work for me was to install the latest NuGet package of System.Net.Http, and use assembly binding redirects in my test project to ensure that it used the 4.2.0.0 version instead of 4.0.0.0.

This is often caused by early versions of nuget packages targeting .NET standard, which have dependencies on OOB ("out-of-band") packages. OOB packages are a kind of polyfill for dlls that are part of .NET framework but not .NET standard. Here is a very good explanation of what happened. In my case, the following helped:
I identified the nuget package that had a dependency on the system.net.http 4.2.0 nuget package, and upgrade that package.
The dependency was no longer present in the upgraded package, so i could uninstall the system.net.http 4.2.0 nuget package.
The upgraded package of course still expects the reference to the system.net.http 4.0.0 assembly, so in case of doubt, you may reinstall the upgraded package to make sure that the assembly reference is in your *.csproj file.

Related

Decompile ASP.NET Core 3.x sources in Rider

I use Rider 2019.2.3 on the Ubuntu 18.10 with installed .NET SDK of version 3.1.100.
When I try to navigate to decompiled sources I sometimes see only declaration of the methods without their implementations, for example:
public static class IdentityServiceCollectionExtensions
{
public static IdentityBuilder AddIdentity<TUser, TRole>(
this IServiceCollection services)
where TUser : class
where TRole : class;
...
}
Rider took this source from the assembly /usr/share/dotnet/packs/Microsoft.AspNetCore.App.Ref/3.1.0/ref/netcoreapp3.1/Microsoft.AspNetCore.Identity.dll. I inspect the IL code of it and it looks like this assembly contains only stubs for methods without their implementations.
So I have a couple of questions:
What is the location of the actual assemblies of ASP.NET Core libraries on my computer?
How can I force Rider to decompile actual assemblies?
My .csproj has Microsoft.NET.Sdk.Web SDK specified, so I thought that maybe I should install some special SDK for web development, but I can't find any information about this.
Navigation into decompiled method body in .NET Core 3.0 fixed in JetBrains Rider 2019.3. Please update your version to the latest available release.
The base path for the implementation assemblies is:
C:\Program Files\dotnet\shared\
I created a simple ASP.NET Core App and added your IdentityBuilder AddIdentity<TUser, TRole> function. When decompiled it couldn't get resolved automatically as well.
The actual assembly path for your case is:
C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\3.1.0\Microsoft.AspNetCore.Identity.dll
On Ubuntu it should be:
/usr/share/dotnet/shared/Microsoft.AspNetCore.App/3.1.0/Microsoft.AspNetCore.Identity.dll
Once i added this file manually to the decompiler i could step through the source code
If the path doesn't exist you might have to install the AspNetCore SDK for Ubuntu.

"Can't resolve reference" when using Azure Service Bus package in Xamarin.iOS

I'm using the Microsoft.Azure.ServiceBus package in my Xamarin.iOS project. This works fine for Debug builds, when linking is off, but when I want to make a Release build for distribution (with the default setting Link Framework SDKs only), it fails with the following error:
/Users/Gerwin/Public/Projects/Sandbox/Test3/MTOUCH: Error MT2101: Can't resolve the reference 'System.Threading.Tasks.Task`1<Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult> Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions::AcquireTokenAsync(Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext,System.String,System.String,Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential)', referenced from the method 'System.Void Microsoft.Azure.Services.AppAuthentication.AdalAuthenticationContext/d__0::MoveNext()' in 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.14.2.11, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. (MT2101) (Test3)
Configuration:
macOS 10.15.1
Visual Studio for Mac 8.3.8 (build 8)
Xamarin.iOS 13.6.0.12
.NET Core SDK 3.0.100
Steps to reproduce:
Create a new iOS app via the wizard
Add the NuGet package Microsoft.Azure.ServiceBus (the latest version, 4.1.1)
Add some code to call the API, e.g. in the FinishedLaunching method in AppDelegate.cs:
InvokeOnMainThread(async () => {
var client = new TopicClient("", "", RetryPolicy.NoRetry);
var message = new Message(new byte[0]);
await client.SendAsync(message);
await client.CloseAsync();
});
(you'll need a using Microsoft.Azure.ServiceBus; too)
Now, a Debug build for the Simulator works fine
However, a Release build for an iOS device produces the error mentioned above
The build output shows a slightly different but related error:
MTOUCH : error MT2101: Can't resolve the reference 'Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate', referenced from the method 'System.Void Microsoft.Azure.Services.AppAuthentication.ClientCertificateAzureServiceTokenProvider/d__8::MoveNext()' in 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.14.2.11, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
Adding the NuGet package Microsoft.IdentityModel.Clients.ActiveDirectory separately doesn't help; disabling linking works, but produces much larger .IPA files. (Which is a problem in my actual app, which uses much more libraries.) I've tried to use the --linkskip option, e.g. using --linkskip=Microsoft.IdentityModel.Clients.ActiveDirectory doesn't help. I ended up using an older version (2.0.0) of the ServiceBus package.

Method Not Found when using LightInject with MVC5 and .Net 4.5

When setting up LightInject for an MVC controller I am getting an error when calling container.EnableMvc(); in the injector setup.
Error:
Method not found:
'Void LightInject.WebContainerExtensions.EnablePerWebRequestScope(LightInject.IServiceContainer)'
Source:
public static void Register() {
var container = new ServiceContainer();
container.ScopeManagerProvider = new PerLogicalCallContextScopeManagerProvider();
WebContainerExtensions.EnablePerWebRequestScope(container);
container.RegisterControllers();
container.Register<ISomeClass, SomeClass>();
container.EnableMvc();
}
Additional Information:
I am running the code locally through Visual Studio
The project is 4.5
My OS is Windows 10 (framework 4.5)
In the past when I have setup LightInject I have set the scope lifetime manually but the documentation, for general setup and MVC specific examples, has since changed. I came across one thread that mentioned this could be an issue with not including LightInject.Web as a dep, but I can see it listed as a dep for LightInject.MVC and in the list of references in the project.
Are there any other steps I can take to manually configure the lifetime or otherwise verify that this method is available before Enabling MVC?
The issue here was that I installed LightInject.MVC with NuGet. It lists it's dependencies as:
LightInject.Web (>= 1.0.0.4)
LightInject (>= 3.0.1.7)
The after I exhausted this being an issue with versions of .Net 4.5 and possible issues with async. I decided to manually update both LightInject.Web and LightInject to their newest versions. After the update it resolved the issue.
I will add this as a bug in the listed dependencies on the projects site.

The server factory could not be located for the given input: Microsoft.Owin.Host.HttpListener

I have implemente signalR in window service.
private IDisposable SignalR { get; set; }
public void Configuration(IAppBuilder app)
{
var hubconfig=new Microsoft.AspNet.SignalR.HubConfiguration();
hubconfig.EnableJSONP = true;
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR(hubconfig);
}
private void StartSignalRServer(StringBuilder sbLog)
{
try
{
this.SignalR = WebApp.Start(ServerURI); //This throws exception
//this.SignalR= WebApp.Start<Startup>(ServerURI);
sbLog.Append(string.Format("{0}--------SignalR Server Started------",Environment.NewLine));
}
catch (Exception ex)
{
sbLog.Append(string.Format("{0}Exception in StartSignalRServer=>{1}", Environment.NewLine,ex.Message));
}
}
Exception:The server factory could not be located for the given input:
Microsoft.Owin.Host.HttpListener
The Microsoft.Owin.Host.HttpListener assembly is a runtime reference in WebApp.Start. You need to include it in the project's references for it to be available for loading. Check the bin\Debug (etc) directory to make sure it's included. May as well add it as a nuget dependency as well.
Install the package:
PM> Install-Package Microsoft.Owin.Host.HttpListener
Install the Microsoft.Owin.Host.HttpListener package from Nuget using:
PM> Install-Package Microsoft.Owin.Host.HttpListener
(unlike an earlier answer you should avoid using -IncludePrerelease in production code)
Hello for same error message but in slithly different context that i have encountered:
Due to stupid referencing optimization which is totally immature regarding reflection. It happens that MsBuild do not copies the Microsoft.Owin.Host.HttpListener.dll in your startup project if it references another project which uses Owin.
In my case I have the error messsage mentioned above and opted for explicit reference in project using Owin by adding explicit use of the problematic dll so that msbuild sees a reference needed so Microsoft.Owin.Host.HttpListener.dll will be copied (not needed for other dll) -This issue come from the fact that owin stuff does reflection inside itself leaving msbuild completely dummy by removing this dll-:
using Microsoft.Owin.Host.HttpListener;
...
_log.Debug("Loading type: "+ typeof(OwinHttpListener) + "..."); // Hack to force copy of Microsoft.Owin.Host.HttpListener.dll on target referencing project
I encountered same error.
In project A -- I am starting owin web service using WebApp.Start() in a function.
In Project B -- I am calling project A's function here. Unfortunately Project B is not my .Net solution's startup project.
Project C is my .Net Solution startup project.
If I Install nuget package using command Install-Package Microsoft.Owin.Host.HttpListener in solution's start up project i.e Project, C it works fine. If I do the same in Project B it does not work. So be careful while installing nuget package.

ServiceStack 3.9.* to 4.*

I am trying to change ServiceStack in my service from 3.9.43 to 4.0.9.
I had to change several things in my code and mostly followed the release notes for this.
There were a couple of weird things for me, like not finding anything to replace ServiceStack.WebHost.Endpoints or AppHostHttpListenerLongRunningBase but I could check those things after and was able to make my code to compile.
The problem is that when I run my code I get this exception in the very begining and it just kills the service:
Method 'ExecuteMessage' in type 'ServiceStack.Host.ServiceController' from assembly 'ServiceStack, Version=4.0.9.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
I get this when hitting the base:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServiceStack;
using ServiceStack.Text;
//using ServiceStack.WebHost.Endpoints;
using ServiceStack.Web;
namespace ThisService {
public class AppHost : AppHostHttpListenerPoolBase { //AppHostHttpListenerLongRunningBase {
public AppHost(int wthreadMax)
: base("This Service " + VcsInfo.ChangesetId, wthreadMax, typeof(ThisService).Assembly) {
}
...
I am referencing in my project:
ServiceStack (4.0.9.0);
ServiceStack.Client;
ServiceStack.Common;
ServiceStack.Interfaces;
ServiceStack.Text
I am sure I am doing something wrong changing to version 4.* and am lost with what is trying to call the Execute Message since I think removed everything from the previous version. Any suggestion to where I should be looking to?
By the way, this a simple service: get json -> math + stuff -> return json.
I want to find out if a bug I found the version 3.9.43 still happens in version 4.0.9 (can't find anything specific about that bug but I believe one fix there is related) to see if I should actually re-factor my code for this version.
Update in v4.10
This should now be resolved in ServiceStack v4.10 where now all NuGet packages specify a minimum version for all dependencies matching the current version. This will force NuGet to pull down the latest packages instead of the oldest matching ones.
NuGet seems to have the weird behavior that it will pull in the lowest dependencies when you install a package, so if you install the latest version of ServiceStack, e.g:
PM> Install-Package ServiceStack -Version 4.0.9
It will pull in the lowest matching dependenices, e.g:
<package id="ServiceStack.Client" version="4.0.3" targetFramework="net45" />
<package id="ServiceStack.Common" version="4.0.3" targetFramework="net45" />
<package id="ServiceStack.Interfaces" version="4.0.3" targetFramework="net45" />
<package id="ServiceStack.Text" version="4.0.3" targetFramework="net45" />
Which is an unexpected surprise. Unfortunately ServiceStack assumes that it's always working with the latest dependencies with the same version it was built with.
So after installing ServiceStack you will need to update all your packages which will bring them in-line with the latest versions, which you can easily do in the Updates tab in the NuGet UI, or in the NuGet Package Console Manager with:
PM> Update-Package
Manually remove any assembly redirects
Installing the previous v4.02 of ServiceStack (now removed) created new assembly redirects for ServiceStack.Interfaces in the Web.config which you should also manually remove if they exist. These now shouldn't be created for new projects.
I had the same problem as well. Therefore I tried installing an older v4 version from Nuget and managed to make it work.
Using Scott's example I can get this to work correctly if I install 4.0.4:
install-package servicestack -Version 4.0.4
If I use version 4.0.5 then it runs but the example web page reports
Method not found: 'Void ServiceStack.Web.IResponse.set_Dto(System.Object)
If I use version 4.0.6 or above then I get the error reported by RGPT.
So, for now it may be a case of using the 4.0.4 version until someone with more knowledge than me replies with a better answer. I've only just starting using ServiceStack today so I don't know much yet ;)
Update: I don't have high enough ServiceStack reputation to post a comment so felt best to edit my original post. The answer below by mythz had the key bit of information. Immediately update your nuget packages after installing and then check the web/config / app.config to see if any dependentAssembly bindingRedirects are hanging around - if so then remove them and away you go :)
I've had a similar problem as well. I followed the upgrade path, first via the Beta channel before upgrading to the offical channel. What I soon realised was that the Beta libraries had version numbers greater than the official channel.
NuGet will check for a more up-to-date version locally first, before pulling in the libraries remotely. Of course, it will pull in ServiceStack v4.0.x from the official channel, but all the dependencies will come from the already downloaded Beta (i.e. locally).
What I did to resolve it:
Uninstall all ServiceStack dependencies from the Solution via NuGet
Deleted the Solution's Nuget '/packages' folder, and to re-import it using NuGet package restore
Re-added the ServiceStack references via NuGet, and checked the 'packages.config' for correct versions

Categories