I have an ASP.NET MVC4 application in which I am creating multiple areas, is there a way I can find out programmatically the number of areas that are present and their names.
The AreaRegistration.RegisterAllAreas(); registers each area route with the DataTokens["area"] where the value is the name of the area.
So you can get the registered area names from the RouteTable
var areaNames = RouteTable.Routes.OfType<Route>()
.Where(d => d.DataTokens != null && d.DataTokens.ContainsKey("area"))
.Select(r => r.DataTokens["area"]).ToArray();
If you are looking for the AreaRegistration themselves you can use reflection to get types which derives from AreaRegistration in your assambly.
AreaRegistration.RegisterAllAreas() cannot be used pre-initialization of the web application. However, if you want to get the areas without calling RegisterAllAreas(), e.g. in an automated test, then the following code may be helpful:
var areaNames = new List<string>();
foreach (var type in typeof(MvcApplication).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(AreaRegistration)))) {
var areaRegistration = Activator.CreateInstance(type) as AreaRegistration;
areaNames.Add(areaRegistration.AreaName);
}
Note that MvcApplication is the class derived from HttpApplication. You can use any class name as long as that class is in the same assembly as the assembly registrations, i.e. the classes derived from AreaRegistration. If you have split up your application with areas in more than one assembly, then you'd need to adapt this code accordingly so it searches all those assemblies.
Related
Apologies if this question has been answered elsewhere, I have had trouble finding any resources on this.
The scenario is this. I have created a custom field in the Tax Preferences screen called Usrapikey.
This value holds an api key for a call that gets done in some custom business logic.
The custom business logic however occurs on the Taxes screen.
So within the event handler I need to access that API key value from the other screen. I have tried instantiating graphs and using linq and bql but to no avail.
below is what I have currently and my error is: No overload for method 'GetExtension' takes 1 arguments
If I am going about this the wrong way please let me know if there is a more civilized way to do this
protected virtual void _(Events.FieldUpdated<TaxRev, TaxRev.startDate> e)
{
var setup = PXGraph.CreateInstance<TXSetupMaint>();
var TXSetupEX = setup.GetExtension<PX.Objects.TX.TXSetupExt>(setup);
var rateObj = GetValues(e.Row.TaxID, TXSetupEX.Usrapikey);
decimal rate;
var tryRate = (Decimal.TryParse(rateObj.rate.combined_rate, out rate));
row.TaxRate = (decimal)rate * (decimal)100;
row.TaxBucketID = 1;
}
Many Thanks!
Well, acumatica support got back. It seems if you want to access the base page use:
TXSetup txsetup = PXSetup<TXSetup>.Select(Base);
To get the extension use:
TXSetupExt rowExt = PXCache<TXSetup>.GetExtension<TXSetupExt>(txsetup);
Then you can access the extension fields like so:
var foo = rowExt.Usrfield;
Is there any tool to update .rgs files to reflect change made in the IDL ?
rgs files are created by the ATL control wizzard but I can't find a way to refresh thoses files.
When we change the uuid of an interface (within the .IDL file), we are forced to changed by hand the "hard copy" values in those .rgs files. This is quiet prone to error.
I found this interesting project that intend to fill this gap but, accordingly the last comments, it didn't works any more since VC2005.
ATL CAtlModule implementation offers virtual CAtlModule::AddCommonRGSReplacements which you can override and add substitutions to remove hardcoded RGS values.
For example, my typical ATL code looks like this:
class CFooModule :
public CAtlDllModuleT<CFooModule>
{
[...]
// CAtlModule
HRESULT AddCommonRGSReplacements(IRegistrarBase* pRegistrar)
{
// Error handling omitted for code brevity
__super::AddCommonRGSReplacements(pRegistrar);
ATLASSERT(m_libid != GUID_NULL);
pRegistrar->AddReplacement(L"LIBID", _PersistHelper::StringFromIdentifier(m_libid));
pRegistrar->AddReplacement(L"FILENAME", CStringW(PathFindFileName(GetModulePath())));
pRegistrar->AddReplacement(L"DESCRIPTION", CStringW(AtlLoadString(IDS_PROJNAME)));
return S_OK;
}
In COM classes I override UpdateRegistry method to add tokens with third parameter of standard call _pAtlModule->UpdateRegistryFromResource.
As a result, many .RGS are shared between COM classes because hardcoded values are replaced with tokens. Specifically, there are no GUIDs in RGS files, e.g.:
HKCR
{
NoRemove CLSID
{
ForceRemove %CLSID% = s '%DESCRIPTION%'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
val AppID = s '%APPID%'
TypeLib = s '%LIBID%'
}
}
}
I'm not able to understand how %CLSID% is replaced with the COM class CLSID in roman-r's answer. There seem to be something missing in the answer.
Alternative solution from CodeProject: Registry Map for RGS files.
This solution introduces a custom registrymap.hpp header with a DECLARE_REGISTRY_RESOURCEID_EX extension that allows you to add RGS substitution macros to your COM classes. Example:
BEGIN_REGISTRY_MAP(CClassName)
REGMAP_ENTRY("PROGID", "MyLibrary.ClassName")
REGMAP_ENTRY("VERSION", "1")
REGMAP_ENTRY("DESCRIPTION", "ClassName Class")
REGMAP_UUID ("CLSID", CLSID_ClassName)
REGMAP_UUID ("LIBID", LIBID_MyLibraryLib)
REGMAP_ENTRY("THREADING", "Apartment")
END_REGISTRY_MAP()
I apologize if my question is not adequately described. I am a .Net / C# / SSIS newbie. Also apologize if already answered, I've tried searching here and Google for a few hours without luck.
Background: I need to pull data rows from a SharePoint 365 list and unpivot certain columns into a format ready for import to a SQL Server table. I realize that SSIS has an Odata Source and built-in Unpivot component, and I've successfully used those for proof of concept.
However, I believe I need a custom script component because the nummber of columns to unpivot from the source SharePoint list is variable. Each month or so, a new column will be added (it relates to a financial forecasting "tool" in SharePoint, and the latest forecasted month changes). My understanding is that source columns must be defined in SSIS at design time, so if my source columns are changing, the only way I can think to address this without manually changing the SSIS data flow each month is to programatically combine the Odata source and unpivot functions into a custom script component.
I understand, or can figure out, the unpivot logic. The part I am struggling with is how to actually connect to and expose a given list and it's data rows / columns as lists that I can loop through and perform my mapping to the output columns.
My "starting point" for requested guidance is this:
1) Created and successfully connected to the SharePoint site in question using standard SSIS Odata Connection Manager.
2) Created standard "Script Component", type = source, on the visual designer.
3) From script component properties, associated the Odata connection manager with the name of "myConnection".
4) Need help -> within the script component, open a connection to a specific list, read it's contents, and perform unpivot logic.
For illustration purposes, assume the source is a SharePoint list with two "fixed" string columns titled Study and Site, and a variable number of columns with names matching month-end dates (e.g. 9/30/2016, 10/31/2016, etc.) that contain integer values. I want to map the study and site source columns to destination columns of the same name and unpivot the month columns where column name is mapped to ProjectionMonth and the integer value is mapped to ProjectionValue.
Here's the basic algorithm I have in mind (I realize this isn't compilable - that's where I need your help!):
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Data.SqlClient;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
IDTSConnectionManager100 connMgr;
SqlConnection sqlConn; // from MSDN tutorial, but I don't know how to adapt to Odata/SharePoint 365 list
SqlDataReader sqlReader; // not sure how to adapt
public override void AcquireConnections(object Transaction)
{
connMgr = this.Connections.myConnection;
sqlConn = (SqlConnection)connMgr.AcquireConnection(null); // This is from MSDN tutorial, but I don't know how to adapt to Odata
}
public override void PreExecute()
{
//Not sure how to adapt to odata to read specific SharePoint list
SqlCommand cmd = new SqlCommand("SELECT * FROM <some sharepoint list>", sqlConn);
sqlReader = cmd.ExecuteReader();
}
public override void PostExecute()
{
sqlReader.Close(); // Not sure how to adapt.
}
public override void CreateNewOutputRows()
{
string myStudy;
string mySite;
string myProjectionMonth;
string myProjectionValue;
// This is a rough representation of the logic needed.
// I realize that the actual code to access column values / names depends on the class(es) I need to use, but not sure what those classes are / how to access
foreach (myListRow in sqlConn.rows)
{
myStudy = myListRow.Columns["Study"].value;
mySite = myListRow.Columns["Site"].value;
foreach (myColumn in myListRow.Columns)
if (DateTime.TryParse(myColumn.Name, out dateValue))
{
myProjectionMonth = myColumn.Name;
myProjectionValue = myColumn.Value;
Output0Buffer.AddRow();
Output0Buffer.Study = myStudy;
Output0Buffer.Site = mySite;
Output0Buffer.ProjectionMonth = myProjectionMonth;
Output0Buffer.ProjectionValue = myProjectionValue;
}
}
}
}
Edit: as an example, assume the source SharePoint list has the following:
Study Site 9/30/2016 10/31/2016
123 ABC 5 10
I want to the script component to connect to the list, read it's contents, and return the following unpivoted data set for eventual load into SQL Server:
Study Site ProjectionMonth ProjectionValue
123 ABC 9/30/2016 5
123 ABC 10/31/2016 10
So this is probably not an ideal way of doing it, and it doesn't leverage the standard SSIS Odata Connection Manager that I wanted... but it does technically get the job done and it's good enough for me, for now.
Would be interested on any suggested feedback / improvements / etc., if you have any.
#region Namespaces
using System;
using Microsoft.SharePoint.Client;
using System.Security;
using System.Collections.Generic;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void CreateNewOutputRows()
{
// Connect to SharePoint
ClientContext context = new ClientContext("https://<redacted>.sharepoint.com/Development");
SecureString passWord = new SecureString();
foreach (char c in Variables.sharepointPassword.ToCharArray()) passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials("<redacted>#<redacted>.onmicrosoft.com", passWord);
// Define the target list
List EnrollmentList = context.Web.Lists.GetByTitle("Enrollment Projections");
// Find all fields in the target list
FieldCollection myFields = EnrollmentList.Fields;
context.Load(myFields);
context.ExecuteQuery();
// Load all rows from the target list
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
ListItemCollection items = EnrollmentList.GetItems(query);
context.Load(items);
context.ExecuteQuery();
//Store valid date fields
List<Field> myDateFields = new List<Field>();
foreach (Field tempField in myFields)
{
DateTime tempDate;
if (DateTime.TryParse(tempField.Title, out tempDate))
{
myDateFields.Add(tempField);
}
}
string myStudy;
string mySite;
string myMonth;
string myValue;
foreach (ListItem listItem in items)
{
myStudy = listItem["Study"].ToString();
mySite = listItem["Site"].ToString();
foreach (Field tempField in myDateFields)
{
myMonth = tempField.Title;
myValue = listItem[tempField.InternalName.ToString()].ToString();
Output0Buffer.AddRow();
Output0Buffer.Study = myStudy;
Output0Buffer.Site = mySite;
Output0Buffer.ProjectedMonth = myMonth;
Output0Buffer.ProjectedValue = Convert.ToInt32(myValue);
}
}
}
}
I need to access some methods and properties of a third party unmanaged DLL from my VS2010 C# project. One property in particular “disappears” when trying to access it after I added the DLL to the reference. I am using MS VS2010 and the target platform is an XP SP3 x86.
From the .NET VB, the Item property is shown as
Item([Object], [Object]) As Object
or
ReadOnly Default Property Item(Optional ByVal Name As Object = Nothing, Optional ByVal Index As Object = Nothing) As Object
I can use it with no problem.
However, in C#, this property disappears and the closest one I can find become
this[[object], [object]]
or
dynamic this[[object Name = System.Type.Missing], [object Index = System.Type.Missing]] { get; }
How do I access this property in my C# project? Thanks.
The Item property in VB.NET is the indexer in C#.
So, the following VB.NET and C# codes are equivalent:
/* VB.NET */
yourObject.Item(o1, o2)
/* C# */
yourObject[o1, o2];
this is an indexer and can be accessed like this.
var yourObj = new SomeObject();
var item = yourObj[value1,value2];
In other words you just use [] brackets after the object variable itself, rather than Item()
I have an application that requires mappings between string values, so essentially a container that can hold key values pairs. Instead of using a dictionary or a name-value collection I used a resource file that I access programmatically in my code. I understand resource files are used in localization scenarios for multi-language implementations and the likes. However I like their strongly typed nature which ensures that if the value is changed the application does not compile.
However I would like to know if there are any important cons of using a *.resx file for simple key-value pair storage instead of using a more traditional programmatic type.
There are two cons which I can think of out of the blue:
it requires I/O operation to read key/value pair, which may result in significant performance decrease,
if you let standard .Net logic to resolve loading resources, it will always try to find the file corresponding to CultureInfo.CurrentUICulture property; this could be problematic if you decide that you actually want to have multiple resx-es (i.e. one per language); this could result in even further performance degradation.
BTW. Couldn't you just create helper class or structure containing properties, like that:
public static class GlobalConstants
{
private const int _SomeInt = 42;
private const string _SomeString = "Ultimate answer";
public static int SomeInt
{
get
{
return _SomeInt;
}
}
public static string SomeString
{
get
{
return _SomeString;
}
}
}
You can then access these properties exactly the same way, as resource files (I am assuming that you're used to this style):
textBox1.Text = GlobalConstants.SomeString;
textBox1.Top = GlobalConstants.SomeInt;
Maybe it is not the best thing to do, but I firmly believe this is still better than using resource file for that...