My policy redirection on GAC is not working - .net-assembly

I created a basic project in WinForms on which I have a .exe that loads a really simple library:
The .exe:
public Form1()
{
InitializeComponent();
int a;
int b;
a = 7;
b = 3;
MessageBox.Show(Sumar.SumResult(a, b));
}
The library:
public class Sumar
{
public static string SumResult(int a, int b)
{
return (a + b).ToString(CultureInfo.InvariantCulture);
}
}
Really simple. The assembly for the first version of the library:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Then I installed v1.0.0.0 on GAC:
gacutil -i TestLibrary.dll
I changed code on the library to be different:
public class Sumar
{
public static string SumResult(int a, int b)
{
return (a - b).ToString(CultureInfo.InvariantCulture);
}
}
And changed assembly version to 1.0.0.1. Then I installed that library to GAC.
The .exe is still consuming 1.0.0.0 .dll, so I create a policy to use v1.0.0.1 instead:
al /link:test.1.0.config /out:policy.1.0.TestLibrary.dll /keyfile:sgKey.snk /platform:x86
Where the .config looks like this:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="TestLibrary"
publicKeyToken="a96822fc2f88c1d9"
cultures="neutral" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="1.0.0.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
After that, I install the policy to GAC:
gacutil /i policy.1.0.TestLibrary.dll
And it says Assembly successfully added to the cache, but my .exe is still using v1.0.0.0.
So, Why didn't my redirect work?

The problem was that the Policy was correct, but the Major and Minor versions were not the same that the one on the .dll, and that's why it didn't work.

Related

Partial platform specific methods in .NET MAUI

I'm trying to implement plattform specific partial method in .NET MAUI to get the connection string for the database.
In the "main application":
namespace TestApp.DL;
public partial class BaseHandler
{
public partial string GetDBPath();
private string GetCnnPath()
{
var dbPath = GetDBPath();
var cnnPath = $"Data Source={dbPath}";
return cnnPath;
}
...
}
in the platform folders in the project:
where each contain the plattform specific implementation:
namespace TestApp.DL;
// All the code in this file is only included on Android.
public partial class BaseHandler
{
public string GetDBPath()
{
var dbName = "com.mycompany.mydatabase.db";
return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
}
}
...but I keep getting "Error CS8795: Partial method 'BaseHandler.GetDBPath()' must have an implementation part because it has accessibility modifiers. (CS8795)". It seems like the platform specific files are not seen by the compiler? Note, they are in a separate assembly project from the main application but that should be ok I guess, given that the fwk created the folders for me?
When you struggle with partials you can keep using partial classes, but avoid using partial methods. This is especially true when creating maui libs, were this approach tends to break, while in maui apps the compilation works fine.
The "quick fix solution", all partial classes must use same namespace obviously:
Shared code, you would want to change NET6_0 to NET7_0 whatever you are using:
public partial class BaseHandler
{
private string GetCnnPath()
{
var dbPath = GetDBPath();
var cnnPath = $"Data Source={dbPath}";
return cnnPath;
}
#if (NET6_0 && !ANDROID && !IOS && !MACCATALYST && !WINDOWS && !TIZEN)
public string GetDBPath()
{
throw new PlatformNotSupportedException();
}
#endif
}
Your platform specific code in platform Platforms/Android:
public partial class BaseHandler
{
public string GetDBPath()
{
var dbName = "com.mycompany.mydatabase.db";
return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
}
}
First of all, your implementation must use the partial keyword as well:
namespace TestApp.DL;
// All the code in this file is only included on Android.
public partial class BaseHandler
{
public partial string GetDBPath()
{
var dbName = "com.mycompany.mydatabase.db";
return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
}
}
Then, you should make sure that you're following the guidelines for multi-targeting: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/configure-multi-targeting#configure-folder-based-multi-targeting
You'll need to update your .csproj file with the following:
<!-- Android -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net6.0-android')) != true">
<Compile Remove="**\Android\**\*.cs" />
<None Include="**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<!-- iOS -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net6.0-ios')) != true">
<Compile Remove="**\iOS\**\*.cs" />
<None Include="**\iOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<!-- Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net6.0-maccatalyst')) != true">
<Compile Remove="**\MacCatalyst\**\*.cs" />
<None Include="**\MacCatalyst\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<!-- Windows -->
<ItemGroup Condition="$(TargetFramework.Contains('-windows')) != true">
<Compile Remove="**\Windows\**\*.cs" />
<None Include="**\Windows\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
Without this, you would see another compiler error because you can only provide one body for any partial method declaration. You need to provide platform specific implementations for each platform and disable the compilation of the ones that are not needed or you can add a default implementation, but then you need file-based multi-targeting instead of platform-based multi-targeting (or a combination of both).
I've had a similar problem already and solved it here: MAUI: How to use partial classes for platform specific implementations together with net7.0 as TargetFramework in the SingleProject?

How to enable bundling in ASP.NET MVC 5

I was playing a little bit to prevent bundling files and now I am stuck at how to return them to be a bundled.
I tried to set debug=false, also I entered BundleOptimization to true and I have files separated.
My BundleCOnfig.cs looks like:
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
#region Styles bundles
var bundlesCSS = new StyleBundle("~/bundles/css")
.Include("~/Content/css/libs/bootstrap/bootstrap.css")
//.Include("~/Content/css/libs/fontawesome/font-awesome.css")
.Include("~/Content/css/libs/camera/camera.css")
.Include("~/Content/css/libs/fontawesome/font-awesome.css", new CssRewriteUrlTransformWrapper());
var bundlesCustom = new StyleBundle("~/bundles/css/custom")
.Include("~/Content/css/custom/general.css")
bundlesCSS.Orderer = new AsIsBundleOrderer();
bundlesCustom.Orderer = new AsIsBundleOrderer();
bundles.Add(bundlesCSS);
bundles.Add(bundlesCustom);
bundles.Add(new StyleBundle("~/bundles/hotel-datepicker-css").Include(
"~/Content/css/libs/baguetteBox.min.css",
"~/Content/css/hotel-datepicker/hotel-datepicker.css"
));
#endregion
}
}
and my web.config looks like this:
<?xml version="1.0"?>
<system.web>
<compilation debug="false" targetFramework="4.7.2"/>
<httpRuntime targetFramework="4.7.2"/>
<httpModules>
<add name="TelemetryCorrelationHttpModule"
type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation"/>
</httpModules>
</system.web>
Have you added below line of code in Application_Start() of Global.asax.cs file?
BundleConfig.RegisterBundles(BundleTable.Bundles);
if yes, then BundleTable.EnableOptimizations = true enables bundling and minification in debug mode. If you set it to false then it will not do bundling and minification.

No assembly found containing a Startup or [AssemblyName].Startup class

I've tried resolving this from answers in other and similar posts, but no luck.
I'm Using MVC 5, framework 4.8 latest VS2017.
Thanks
My Config is: (including other attempts)
<configuration>
<appSettings>
<!--<add key="owin:AutomaticAppStartup" value="false" />-->
<add key="owin:HandleAllRequests" value="true"/>
<!--<add key="owin:AppStartup" value="Api.xxx" />-->
</appSettings>
</configuration>
Startup class is:
[assembly: OwinStartupAttribute(typeof(Api.xxx.Startup))]
namespace Api.xxx
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Allow all origins
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
….
}
}
}
and Api is:
namespace Api.xxx
{
[Route("values")]
public class ValuesController : ApiController
{
private static readonly Random _random = new Random();
public IEnumerable<string> Get()
{
var random = new Random();
return new[]
{
_random.Next(0, 10).ToString(),
_random.Next(0, 10).ToString()
};
}
}
}
I think you need to change
[assembly: OwinStartupAttribute(typeof(Api.xxx.Startup))]
to
[assembly: OwinStartup(typeof(Api.xxx.Startup))]
Reference: https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-startup-class-detection

Load resource dictionary in wpf add in application

Hi i need to make multilingual WPF office add-in. I want to use resources files. i call in my ThisAddIn_Startup function my SetLanguageDictionary
public static void SetLanguageDictionary()
{
try
{
//Get the assembly information
System.Reflection.Assembly assemblyInfo = System.Reflection.Assembly.GetExecutingAssembly();
Uri uriCodeBase = new Uri(assemblyInfo.CodeBase);
string path = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString());
ResourceDictionary dict = new ResourceDictionary();
switch (Thread.CurrentThread.CurrentCulture.ToString())
{
case "en-US":
dict.Source = new Uri(path + "\\Resources\\en-US.xaml",
UriKind.Absolute);
break;
case "fr-FR":
dict.Source = new Uri(path + "\\Resources\\fr-FR.xaml",
UriKind.Absolute);
break;
default:
dict.Source = new Uri(path + "\\Resources\\en-US.xaml",
UriKind.Absolute);
break;
}
Application.Current.Resources.MergedDictionaries.Add(dict);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
my resources files are there
<ResourceDictionary
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="Ready">Ready</system:String>
<system:String x:Key="login">Login</system:String>
<!-- All StringResources Goes Here -->
</ResourceDictionary>
when loading i have the error :
System invalid operation exception : operation error loadfrom resouceDictionary with URI:"file:///c:
thanks for your reply
I solve my problem. It s just because load of resourcesdictionary could only be done by code behind xaml page.
You need to insert in File App.xaml the direction of your files.. in my case for example:
<Application x:Class="VBControl.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VBControl"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\StringResources.xaml"/>
<ResourceDictionary Source="Resources\StringResources.en-EN.xaml" />
<ResourceDictionary Source="Resources\StringResources.pt-BR.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Return a Folder GUID from a SharePoint Custom Workflow Activity

Has anybody ever written code to return the GUID of a folder in SharePoint Workflow Activity so I can then pass it into a Workflow Variable?
Would be really keen to see a code sample if you have one!
Thanks
I've done something similar, and I can offer a few tips. I didn't find code samples, so I copied code from SharePoint's DLLs using Reflector.
File: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI\microsoft.sharepoint.WorkflowActions.dll
Class (for example): Microsoft.SharePoint.WorkflowActions.WaitForActivity
You'll find three properties and DependencyPropertys:
[Browsable(true), ValidationOption(ValidationOption.Required), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return (WorkflowContext)base.GetValue(__ContextProperty); }
set { base.SetValue(__ContextProperty, value); }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), Browsable(true), ValidationOption(ValidationOption.Required)]
public string __ListId
{
get { return (string)base.GetValue(__ListIdProperty); }
set { base.SetValue(__ListIdProperty, value); }
}
[Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), ValidationOption(ValidationOption.Required)]
public int __ListItem
{
get { return (int)base.GetValue(__ListItemProperty); }
set { base.SetValue(__ListItemProperty, value); }
}
public static DependencyProperty __ContextProperty;
public static DependencyProperty __ListIdProperty;
public static DependencyProperty __ListItemProperty;
And this in a static constructor:
static MyActivity()
{
__ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(MyActivity));
__ListIdProperty = DependencyProperty.Register("__ListId", typeof(string), typeof(MyActivity));
__ListItemProperty = DependencyProperty.Register("__ListItem", typeof(int), typeof(MyActivity));
}
Bind them on your actions file:
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/>
<Parameter Name="__ListId" Type="System.String, mscorlib, mscorlib" Direction="In" />
<Parameter Name="__ListItem" Type="System.Int32, mscorlib, mscorlib" Direction="In" />
</Parameters>
This can be copied from the file
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow\WSS.ACTIONS
Then, it sould be relatively easy to get the GUID, and return it using a property and out parameter binding.

Resources