Accessing custom project flavor property stored in .csproj file - visual-studio-extensions

OK, so I've managed to create a custom project flavor with a custom property page. It all works and the values are being saved to the .csproj file like such:
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{880389B4-B814-4796-844B-F0E1678C31D1}" Configuration="Debug|Any CPU">
<ServiceLibraryProjectFlavorCfg>
<BooleanProperty>True</BooleanProperty>
</ServiceLibraryProjectFlavorCfg>
</FlavorProperties>
<FlavorProperties GUID="{880389B4-B814-4796-844B-F0E1678C31D1}" Configuration="Release|Any CPU">
<ServiceLibraryProjectFlavorCfg />
</FlavorProperties>
</VisualStudio>
What I cant seem to figure out is how to access this custom property from, say, a menu item callback in my package. I can get the project that the selected item in the solution explorer which was right clicked belongs to, but I'm stuck after that...
Any help will be appreciated
Thanx
Hein

OK, I figured it out.
As part of creating a custom project flavor, you inherit from FlavoredProjectBase and implement the IVsProjectFlavorCfgProvider interface.
the IVsProjectFlavorCfgProvider has one implementable method
int CreateProjectFlavorCfg(IVsCfg pBaseProjectCfg, out IVsProjectFlavorCfg ppFlavorCfg)
So here I implemented a static mapping between my custom IVsProjectFlavorCfg and the specified IVsCfg
Already having a EnvDTE.Project reference, I could then use the following to get a IVsCfg reference:
IVsHierarchy hierarchy1 = null;
var sol = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution;
sol.GetProjectOfUniqueName(project.UniqueName, out hierarchy1);
IVsSolutionBuildManager bm = Package.GetGlobalService(typeof(IVsSolutionBuildManager)) as IVsSolutionBuildManager;
IVsProjectCfg[] cfgs = new IVsProjectCfg[1];
bm.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy1, cfgs);
IVsCfg cfg = cfgs[0] as IVsCfg;
I could then use the IVsCfg reference to look up my custom configuration provider.

If you can access the project node instance (and if your project system is based on MPF), you can just use the GetProjectProperty method of the ProjectNode class. It obtains a ProjectPropertyInstance and returns its evaluated value, or null if the property does not exist.

Related

Why my DevExpress v14.1 doesn't have the GridViewEdittingMode component?

According to the official document of DevExpress : https://documentation.devexpress.com/#AspNet/DevExpressWebGridViewEditingModeEnumtopic , the assembly which contains GridViewEditingMode component should be DevExpress.Web.v14.1.dll. However, I tried to add it to my reference, it still said GridViewEditingMode does not exist. The hash code of my DevExpress.Web.v14.1.dll is SHA256 CFDE95612BA9D4A771DD0236D95A8A1881BE983DC72985205E36134CA37D1075. Worse still, I don't have the project converter in my computer, nor does DevExpress provide v14.1 trial anymore.
Is there any one who knows how to make GridViewEditingMode component be available in a DevExpress v14.1 based project?
Looks like you faced this breaking change (Some classes related to DevExpress ASP.NET controls have been moved to the DevExpress.Web namespace). So, the namespace where the GridViewEditingMode enumeration is implemented was changed from DevExpress.Web.ASPxGridView to DevExpress.Web. The following code should work for you.
var grid = Html.DevExpress().GridView(settings =>
{
settings.Name = "GridView";
// code
settings.SettingsEditing.Mode = DevExpress.Web.ASPxGridView.GridViewEditingMode.EditFormAndDisplayRow;
// code
});

How to pull captions from user-specific Resource Files?

I have two Resource files under the app_GlobalResources folder in my Website project, (CaptionsA.resx and CaptionsB.resx), for CustomerA and CustomerB,respectively.
For example, in CaptionsA.resx, I have:
MyButtonText ------> Click me!
And in CaptionsB.resx, I have:
MyButtonText ------> Click Here
I have to use captions on multiple pages in my Website. But, when CustomerA uses the website all the captions from CaptionsA.resx should be visible and when CustomerB uses the website all the captions from CaptionsB.resx should be visible. Keep in mind that both customers use English as the website language, So I can't use the culture/language localization thingy.
What I want to ask is:
How to programmatically tell my website which Resource file to use when?
What to write in my VB.net code?
How to access the Resource File in my code?
If CustomerType = CustomerA
//RETRIEVE DATA FROM CaptionsA.resx (How to do this?)
else If CustomerType = CustomerB
//RETRIEVE DATA FROM CaptionsB.resx (How to do this?)
And what shall I write in the aspx source file?
<asp:Label ID="LblButtonText" runat="server" Text="<%$ Resources:**WHAT-TO-WRITE-HERE?**,MyButtonText %>"></asp:Label>
I have been searching a lot and have tried to find the answer on a gazillion forums, but threads related to this topic were mostly unanswered or were not helpful.
here is how you do it..
Dim resourceFileBaseName As String = "WebApplicationNamespace.app_GlobalResources.CaptionsA"
Dim isCustomerB As Boolean = True
If isCustomerB Then
resourceFileBaseName = "WebApplicationNamespace.app_GlobalResources.CaptionsB"
End If
Dim customerBasedResourceManager = New System.Resources.ResourceManager(resourceFileBaseName, GetType(CaptionsA).Assembly)
Dim resourceManagerField = GetType(CaptionsA).GetField("resourceMan", BindingFlags.[Static] Or BindingFlags.NonPublic)
resourceManagerField.SetValue(Nothing, customerBasedResourceManager)
All ResX files generate an equivalent class (e.g. CaptionsA) which have an underlying ResourceManager which points to the CaptionsA resource containing all the strings. Based on the customer type, we can make this resource manager point to the right underlying resx file. but this Resource Manager is internal to the class, hence we need to reflect and set the value. Also, the CaptionsA and CaptionsB have no relation to each other, otherwise we could have leveraged some pattern/casting to access their members.
what we're doing in the above code is:
set the right resource file base name based on the customer type. (ensure you're using the right namespace path for the classes)
create a custom resourcemanager which points to our actual resx file.
set the CaptionsA class' resourcemanager to our custom one by reflection.
now whenever you try to access a resource, based on the underlying resx it'll access captionsA.resx or CaptionsB.resx.
one thing you'll notice is that you'll be accessing resources of CaptionsB.resx too via CaptionsA class. this is unavoidable and is the closest to the culture based seamless resource access we can get via non-culture based varying resources.
for the fun of it, here is the C# code as well.
string resourceFileBaseName = "WebApplicationNamespace.app_GlobalResources.CaptionsA";
bool isCustomerB = true;
if (isCustomerB)
{
resourceFileBaseName = "WebApplicationNamespace.app_GlobalResources.CaptionsB";
}
var customerBasedResourceManager = new System.Resources.ResourceManager(resourceFileBaseName,
typeof(CaptionsA).Assembly);
var resourceManagerField = typeof(CaptionsA).GetField("resourceMan", BindingFlags.Static | BindingFlags.NonPublic);
resourceManagerField.SetValue(null, customerBasedResourceManager);
CaptionsA.MyButtonText will point to the value based on the customer type's resx file.

Component will not delete

I'm doing a bit tidy of the Content Manager and have a component that won't delete (not the same as my other question).
When I try to delete the component in question I get the following error
(8004032D) This item is in use.
Unable to delete Component (tcm:4-65020).
UtilitiesBL.AssertItemCanBeDeleted
UtilitiesBL.AssertItemCanBeDeleted
ComponentBL.Delete
Component.Delete
Request.Delete
When I use the Where Used tool on the component I get no results in the "Used In" tab, one result in the "Uses" tab, the "Blueprint Hierachy" shows it is not localized in any of my three child publications and no results in the "Published To" tab.
I have had a look in the Content Manager database to see if I can spot what is going wrong but not really found anything.
Any ideas?
Thanks in advance.
It looks like the Where Used tool in R5.3 isn't working correctly. The component in question is used in 15000 other components. I found this by using the TOM API directly.
var componentID = "tcm:4-65020";
TDS.TDSE tdse = new TDS.TDSE();
var component = (TDS.Component)tdse.GetObject(componentID, TDSDefines.EnumOpenMode.OpenModeView);
var whereUsedString = component .Info.GetListUsingItems();
Now comes the task of deleting all these links...

push external multimedia file in to package at tridion publish time

When we publish some page/dynamic component from tridion is it possible to add some external multimedia file/content(ex:jpg image) in to current executing/rendering package at publish time.So that final transportation package has this binary file present along with original published content?
Is this achivable using customization of tridion renderer/resolver?If yes please provide some inputs.
*Note:*The binary content that needs to be pushed in to package at publish time is not present as multimedia component in tridion, it is located at other file location outside tridion CMS.Instead we have some stub multimedia component being used inside published component/page which has some dummy image. we plan to replace the stub image with original image at publish(rendering/resolving) time.
Since we have huge bulk of binary content stored in DAM tool we dont want that data to be recreated as multimedia component in tridion, insted we want to use that data by querying DAM tool and attach it in to tridion package with some logical referencesplanning to maintain one to one mapping between stub multimedia comp tcmid to original content in some mapping DB for reference).
Please let us know if any solution is there to attach external binary content to package at publish time.
The best - and easiest way - is to use the mechanism provided by Tridion out-of-the-box for this. Create a new multimedia component, select "External" in the resource type drop-down, and type the URL to the object. As long as you can address it with a URL, it will work exactly as you want (item will be added to package and sent to delivery server).
If this is not good enough for you, then yes, you can add it to the package yourself. I've done this in the past with code somewhat like this:
FileInfo file = // Weird logic to get a FileInfo object from external system
Item item = package.GetItem("My original Item");
item.SetAsStream(file.OpenRead());
This replaced the content of my original component with the actual file I wanted. This will work for you IF the original component is also a multimedia component. If it's not, just create a new item with your own name, etc. If possible, do use the out-of-the-box process instead.
PS: FileInfo Class.
As Nuno suggested the best way is to use multimedia component with 'External' resource type. You may not need to create these manually, you can automate using core services or API programs.
Another way I used before to create zip file at run time and add same to package with following code. Hope it may help.
using (MemoryStream ms = new MemoryStream())
{
zip.Save(ms);
downloadAllInOneURL = String.Format("ZipAsset{0}.zip", uniqueZipID);
downloadAllInOneURL = m_Engine.PublishingContext.RenderedItem.AddBinary(ms, downloadAllInOneURL, "", "application/zip").Url;
downloadAllInOneSize = getSize(ms.Length);
}

Where do I put Pluralization rules in asp.net mvc3

I want to add specialized Pluralization rules to my project as I have names in my database like FAS and other things that end with "s" and I want those to be FAS and FASs but the default pluralization wants to make it FASes or something similar which I dont want. I am then trying to use this guide http://blogs.msdn.com/b/efdesign/archive/2008/12/02/pluralization.aspx but I have a hard time figuring out where to put this code? How do I make sure this code is run at startup of my project (I suppose it has to run at startup?)
So where do I put this code?
PluralizationService pluralizationService =
PluralizationService.CreateService(
new CultureInfo("en-US"));
ICustomPluralizationMapping mapping =
pluralizationService as ICustomPluralizationMapping;
if (mapping != null) // it shouldn't be but just checking
{
//Specifying the child pluralizes as children
mapping.Add("FAS", "FASs");
}
The answer is in the tutorial: you have to use it with the schema generator to create the schema using the pluralization service:
EntityModelSchemaGenerator generator =
new EntityModelSchemaGenerator(
storageModel,
"MyNamespace",
"MyContainer",
pluralizationService);
//Generate CSDL and MSL (in memory)
generator.GenerateMetadata();
When do you need to get the names of the entities pluralized?
I may be way wrong, but it seems to me that you could simply add the tables to the model and just rename them in the designer.
Am I overlooking some information?

Resources