I am loading different assemblies using Mono.Cecil and I would like to know if the assembly is targeting .NET Framework or .NET Core.
What I have tried is retrieving the custom attribute TargetFrameworkAttribute :
[assembly:TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework)]
using the code below
var targetFrameWorkAttributes = assemblyDefinition.CustomAttributes
.Where(attribute => attribute.AttributeType.Name == nameof(TargetFrameworkAttribute));
var customAttribute = targetFrameWorkAttributes.FirstOrDefault();
var customAttributeValue = customAttribute?.ConstructorArguments.FirstOrDefault().Value.ToString();
The problem here is that not all assemblies have this attribute in their metadata.
My question is :
Is there any other way to detect if an assembly is targeting .NET Core or .NET Framework runtime other than retrieving custom attribute?
N.B. I have thought for .NET Core I could somehow parse *.deps.json and retrieve runtimeTarget object, but it's only for .NET Core and it would be complicated.
"runtimeTarget": {
"name": ".NETCoreApp,Version=v3.1",
"signature": ""
}
Related
I'm trying to reference dlls in my dotnet core project that are using Entity framework standard, not core.
The problem that i'm running into with dotnet core is that the connection strings that are defined in the appsettings.json are not being read by the referenced dlls, so I get the error:
Message=No connection string named 'Entities' could be found in the application config file.
In the dotnet core app I'm able to get the connection string using EF core with:
"ConnectionStrings": {
"Entities": "my connection info", // this works
},
services.AddDbContext...
This all works. The problem that I run into now is that a lot of our legacy code is .net standard, and i'd prefer to just continue to use them as libraries for now.
Where it fails in the referenced libraries is when
using (var context = new Entities()) // here
Do I need to modify the entity framework layer in the referenced libraries so that they can accept a connection string as a parameter? That would require a lot of updating very old code.
I have a .net Core 3.0 application attempting to invoke .Net Framework 4.8 via reflection. Our goal is to read encrypted AppSettings.config (xml) with ConfigurationManager, which is not possible in .Net Core. Unencrypted yes, but encrypted (CipherData), no.
My reflection code that accesses a static class & method goes like this:
Assembly assembly = Assembly.LoadFrom(exeFullName);
MethodInfo method = assembly.GetType(nameSpacenClass).GetMethod(methodName);
if (method != null)
{
object rtnVal = method.Invoke(null, new object[] { jsonParms });
return rtnVal;
}
else
return null;
The method.Invoke errorred out with this exception message:
FileNotFoundException: Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
So I wrote a proxy program in .Net Framework 4.8, and use the same code to access the code that reads encrypted config via reflection, and it works fine.
Then, I coded .net Core 3.0 to access that proxy via reflection, and it fails. The proxy .Net Framework 4.8 has no references whatsoever. It is barebone. Yet core still requires ConfigurationManager even though the proxy does not. The Config program has only one reference - to System.Configuration.
Core 3.0 => Encrypted App.config => Failed
Core 3.0 => ConfigProgram 4.8 => App.Config => Failed
ConfigProgram 4.8 => App.config => Works
Proxy 4.8 => ConfigProgram 4.8 => App.Config => Works
Core 3.0 => Proxy 4.8 => ConfigProgram 4.8 => App.Config => Failed
I guess the referenced System.Configuration is not required for Reflection invoke by 4.8 but is required even though trough a barebone stepping stone, by .Net Core 3.0. Could someone help me please?
When you load an assembly built for .NET Framework via reflection on .NET Core, it does not load any parts of .NET Framework - just your assembly ("user cod"). And some parts may or may not work. In your case it fails because the requested classes / assemblies of the code compiled for .NET Framework is not part of .NET Core.
This is the reason why only the cases where you start a .NET Framework application to begin with - thus booting up the .NET Framework Runtime - work for you.
I can't return Value Tuple from C# Class Library to ASP.net Core 2.1 MVC app, so I made a new solution to test only that point and it still did it.
Class Library (.net Framework 4.7):
namespace ClassLibrary1
{
public class Class1
{
public (bool Success, string ReturnMessage) abc()
{
return (true, "hi");
}
}
}
.net Core 2.1 MVC Controller:
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public string Index()
{
var c = new Class1();
var x = c.abc();
return "";
}
}
}
I get this error in the MVC app at c.abc():
Reference to type 'ValueTuple<,>' claims it is defined in 'mscorlib', but it could not be found
If I create and return a Value Tuple within either project, it works.
I found this but it didn't help to install those Nuget packages (also why would that be required)?
Predefined type 'System.ValueTuple´2´ is not defined or imported
How can I successfully call this from the MVC app?
you cannot call .Net Framework 4.7 class library from Asp.Net Core.
You can use .Net Standard, or ASP.Net Core for your Class Library.
In my case it worked when I build the project with .Net framework 4.7 instead of older versions. it seems that this feature only works on .Net framework 4.7.
Thank You Derviş Kayımbaşıoğlu your answer helped
As stated in official document, I am trying to implement UseOwin in the Startup.cs.I am trying to use/port IAppBuilder (Microsoft.Owin.Builder.AppBuilder) inside IApplicationBuilder (Microsoft.AspNetCore.Builder.IApplicationBuilder). I had legacy code written using IAppBuilder running fine on .Net Framework 4.5.
I have seen couple of examples about using IAppBuilder in IAplicationBuilder e.g. example 1 example 2. These attempts were about .netcore 1.1 and not .net core 2.0. May be this is the reason i am unable to port.
Please share your thoughts whether i am trying to achieve something not possible at the moment in .net core 2.0 or there is some error in my code.
Note:
I am using dotnetcore 2.0 with Visual Studio 2017
Error
I am getting following error.
return owinAppBuilder.Build,
Task>>(); TypeLoadException: Could not load type
'System.Security.Cryptography.DpapiDataProtector' from assembly
'System.Security, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a'.
My attempt
app.UseOwin(setup => setup(next =>
{
var owinAppBuilder = new AppBuilder();
var aspNetCoreLifetime =
(IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
new AppProperties(owinAppBuilder.Properties)
{
OnAppDisposing = aspNetCoreLifetime?.ApplicationStopping ?? CancellationToken.None,
DefaultApp = next,
AppName = "test"
};
// Only required if CORS is used, configure it as you wish
var corsPolicy = new System.Web.Cors.CorsPolicy
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = true,
SupportsCredentials = true
};
//corsPolicy.GetType()
// .GetProperty(nameof(corsPolicy.ExposedHeaders))
// .SetValue(corsPolicy, tusdotnet.Helpers.CorsHelper.GetExposedHeaders());
owinAppBuilder.UseCors(new Microsoft.Owin.Cors.CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(corsPolicy)
}
});
PublicClientId = "self";
OAuthAuthorizationServerOptions OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new Microsoft.Owin.PathString("/Login"),
Provider = new MyServiceProvider(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
AllowInsecureHttp = true,
RefreshTokenProvider = new MyRefreshTokenProvider(),
};
owinAppBuilder.UseOAuthBearerTokens(OAuthOptions);
//owinAppBuilder.UseTus(context => new DefaultTusConfiguration
//{
// // Excluded for brevity, use the same configuration as you would normally do
//});
return owinAppBuilder.Build<Func<IDictionary<string, object>, Task>>();
}));
Microsoft.Owin and related packages do not have targets for .NET Core, no for .NET Standard. All they have is dlls targeting full .NET. You can reference such libraries from your project targeting .NET Core, but they are not guaranteed to work, as you see yourself, because API (set of classes\methods\signatures) of full .NET and .NET Core are different. Visual Studio even will show a warning when you are doing that, for example:
Package 'Microsoft.Owin 3.1.0' was restored using
'.NETFramework,Version=v4.6.1' instead of the project target framework
'.NETCoreApp,Version=v2.0'. This package may not be fully compatible
with your project.
There is Microsoft.AspNetCore.Owin package and you can use OWIN middleware in .NET Core app as your first link describes, but almost all it provides is UseOwin extension method. There is no AppBuilder type there and so on, and there are no Microsoft.AspNetCore.Owin.Cors packages or similar. So you have to either implement all that yourself (no reason to, because you can use the same functionality provided by asp.net core framework) or wait for OWIN packages that target .NET Standard\Core and do that (didn't check, maybe they even exist already).
So, your code uses packages which are indeed not compatible with your target framework, as exception you have at runtime shows. So another answer (for some reason downvoted) is technically correct.
If you still want to use those packages reliably - you need to target full .NET Framework and not .NET Core. To do that, open your .csproj file and change
<TargetFramework>netcoreapp2.0</TargetFramework>
To some .NET framework version that supports .NET Standard 2.0, for example:
<TargetFramework>net47</TargetFramework>
Then go to nuget package manager and, if you have microsoft.aspnetcore.all package (or other packages targeting .NET Core) - uninstall it, you don't need it anyway. Then install Microsoft.AspNetCore package and all other asp.net core packages you need (if not installed already). Rebuild, run and it will work just fine.
That works because all (most?) AspNetCore packages target .NET Standard, not .NET Core, and you can use them in projects targeting full .NET Framework.
Note that by doing that you have asp.net Core project, but not on .NET Core, with all consequences that come from that (cannot run with dotnet run, on linux need to run with mono, and so on).
The Microsoft.Owin components will not work on dotnet core 2.0, they only work on .NET 4.5+
I'm using Rhino Mock 3.5 for .Net Framework 2.0 and when I run this code I get a run time error.
This is the code
IFile fileInterface = MockRepository.GenerateStub<IFile>();<br>
IUrlMapper urlMapper = MockRepository.GenerateStub<IUrlMapper>();
// this is the line causing the run-time error<br>
HttpContextBase mockHttpContext = MockRepository.GenerateMock<HttpContextBase>();
HttpRequestBase mockRequest = MockRepository.GenerateMock<HttpRequestBase>();
RhinoMocksExtensions.Stub<HttpContextBase,HttpRequestBase>(mockHttpContext, delegate(HttpContextBase ctx)
{
return ctx.Request;
}
).Return(mockRequest);
RhinoMocksExtensions.Stub(fileInterface, delegate(IFile f)
{
f.Exists(Arg<string>.Is.Anything);
}
).Return(true);
AspxReplacementResolver resolverToTest = new AspxReplacementResolver(mockHttpContext, fileInterface, urlMapper);
This is the Error:
TestCase 'TestMockingRhinoMock35.TestTestFixtures.Test1'
failed: System.TypeLoadException : Could not load type 'System.Web.RequestNotification' from assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'......
System.Web.RequestNotification is part of Framework 3.0 but I'm using Framework 2.0 and I referenced the specific Rhino Mocks 3.5 for Framework 2.0 dll.
Thank you
HttpContextBase doesn't exist in .Net framework 2.0. It was added in a .dll called System.Web.Abstractions, and is only available if you've installed the .Net Framework 3.5, as well as Service Pack 1 for .Net Framework 3.5.
You'll have to target .net 3.5 if you want to mock this out. If you're using a seperate assembly for testing, there's no reason you couldn't target your test assembly to 3.5 and leave your production application alone.