Generating CRM Proxy classes as separate files - c#

I have been using and old assembly that references a Dynamics CRM tenant. The assembly contains (among other things) the proxy classes for the tenant. I need to update the proxy classes to the most recent version.
I have used crmsvcutil.exe in the past to generate the proxy class filefor a tenant, but in this assembly the classes each in their own separate files. For example, there is a 'person' c-sharp file which contains the variables of the person entity and the get/set methods.
The current files are in the following format:
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Xml.Serialization;
namespace CRM2011.Proxy.Organisation
{
[GeneratedCode("System.Xml", "4.0.30319.1"), DesignerCategory("code"), DebuggerStepThrough, XmlType(Namespace = "http://schemas.microsoft.com/crm/2007/WebServices")]
[Serializable]
public class thr_offer : BusinessEntity
{
private Lookup createdbyField;
private CrmDateTime createdonField;
//More variables here
public Lookup createdby
{
get
{
return this.createdbyField;
}
set
{
this.createdbyField = value;
}
}
public CrmDateTime createdon
{
get
{
return this.createdonField;
}
set
{
this.createdonField = value;
}
}
//More get/set methods here
}
These appear to have been generated by a tool, but I don't know of any tool that will do this. If I can generate files such as these instead of the monstrous file generated by crmsvcutil.exe it will make development much easier.
Any ideas?

The files were generated with the CRM 4.0 SDK (the CrmDateTime rang a bell).
With the CrmSvcUtil.exe from the CRM 4.0 SDK it is possible to generate separate files, as documented here:
http://msdn.microsoft.com/en-us/library/ff681563.aspx
/out parameter
Determines the name of the .cs or .xml output file and whether there
is one file or one per entity. It may include a full path. If you
specify a name that does not end with .cs or .xml, CrmSvcUtil will
write an individual .cs file for every entity in the system to the
folder you specify. For example, /out:MyClasses outputs a class file
(.cs) for every entity to a folder called MyClasses.However,
/out:MyClasses.cs outputs a class file (MyClasses.cs) that contains
all entities.
This "feature" has been removed from CRM 2011 SDK (if you try to specify the name without the file extension it will still generate a single file)

You'd either have to create a splicer that splices the entities for you after they've been generated into a single file, or create CrmSvcUtil extensions that perform this basic change of behavior for you.
Edit Which the Early Bound Generator in the XrmToolBox does via configuration.

CrmSvcUtil contained in Microsoft.CrmSdk.CoreTools 9.1.0.108 support splitting entities (and other types) into single files using commandline arguments /splitfiles and /outdirectory.
NOTE: The CrmSvcUtil is not 100% clear about the /splitfiles argument, as it is referenced as /SplitToFiles by itself. 🙄

Related

Specifying cs file to build with dotnet CLI

Suppose I have two files in my current working directory:
// file1.cs
Console.WriteLine("file1");
//file 2.cs
Console.WriteLine("file2");
In powershell, I do a dotnet new and delete the automatically generated Program.cs file. Then I do a dotnet build and get an error:
Only one compilation unit can have top level statements
I understand why this occurs, but I would like to be able to have full control of which .cs file is being targetted, while the other ones get ignored.
Is there any way to achieve this without having to create a whole new project for every file?
Doing this with .NET doesn't seem to be possible as of now. An issue on the dotnet/sdk GitHub has requested for this feature to be implemented.
However, you can use the C Sharp Compiler to compile a Windows executable and specify a .cs file with csc file1.cs
file1.cs:
using System;
Console.WriteLine("File 1");
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements
These files both use top-level statements. It implies that they both contain the Main method where program execution starts. You can only have one entry point. Generally, C# code is going to be contained within classes. Define a class in one (or both) files and put your methods within.
// Program.cs
public class Program
{
static void Main()
{
Console.WriteLine("Program.cs");
}
}
// Util.cs
public class Util
{
public static void Display()
{
Console.WriteLine("Util.cs");
}
}

Can't import classes from same namespace

I'm fairly new to .NET and I'm trying to get an old program to work that no longer has it's .csproj file. I've managed to receive an old .sln file from the creator and opened the solution in VS.
From what I can see this is a Developer Web Server project?
Here is the issue.
In the folder Smreka there are 2 files, log.cs and smreka.cs. The log.cs contains the implementation of a class Logger, which I am trying to import in to smreka.cs. They are both using the same namespace Bum.Iglavci.Smreka so as far as I know, I should be able to import the Logger class without any issues.
The problem is that the compiler just can't see it. If I try to directly import it with using static Bum.Iglavci.Smreka.Logger;, I get an error Feature 'using static' is not available in C# 5. Please use language version 6 or greater.
I would like to know why the namespace can't see each other. Is it because I'm missing the .csproj file? Does Developer Web Server even need a .csproj file? If so what's the best way to generate one?
EDIT:
Due to some confusion I'll try to add more details regarding how log.cs and smreka.cs look like. The files are actually a lot longer but I think this should give an idea.
log.cs:
namespace Bum.Iglavci.Smreka{
public class Logger{
public Logger(){
}
public void DoSomething(){}
}
}
smreka.cs:
namespace Bum.Iglavci.Smreka{
public class Baza{
private Logger log;
public Baza(){
log = new Logger();
}
}
}
The compiler has no idea what Logger is under property private Logger log; It states the error The type or namespace name 'Logger' could not be found (are you missing a using directive or an assembly reference?)
I think the namespace is correctly placed, that's why i have a feeling there's something wrong with the project or the solution itself that i need to fix.
Since both classes are in the same namespace they are already able to use each other. You can acces the class by simply doing the following. Let's take Log as the class to call the other class.
Log class:
namespace Bum.Iglavci
{
public class Log
{
public static void ExecuteDoSomething()
{
Smreka.DoSomething();
}
}
}
Smerka class:
namespace Bum.Iglavci
{
public class Smerka
{
public static void DoSomething()
{
//execute code here
}
}
}
It could be possible that the files have the Buil Action property set to
None this will not compile the files. Set it to C# Compiler, this should solve it.
If you don't know how to acces the properties of a file.
Right click the file
Navigate to Properties in the bottom of the list
Set the Build Action to C# compiler (see image)
I found no simple solution. I now created a new .net framework application project and added the files in to the new project. For some reason the namespace works correctly now and the files can see each other in the same namespace.
Yes the error comes from the fact that you don't have a .csproj file.
Such files contain the list of files to compile when building a project. Just having the solution file is not enough.
I suggest some readings on project and solution using Visual Studio :
https://learn.microsoft.com/en-us/visualstudio/ide/solutions-and-projects-in-visual-studio?view=vs-2022
https://learn.microsoft.com/en-us/visualstudio/get-started/tutorial-projects-solutions?view=vs-2022

How to Get Sensitive Information Into SSIS Script Component in a Data Flow

I have an SSIS data flow that contains a script Component as a source. I'd like to generate the source data by running a script on an SQL Server database. The connection string to be used to connect to the database is set to be sensitive. How can I read this sensitive parameter inside the script component using C#?
In a Script Task, usually it is read for example as the following:
string mySecretPassword = Dts.Variables["$Project::MySecretPassword"].GetSensitiveValue().ToString
The Variable class in a Script Task has a GetSensitiveValue method. However, the Script Component Variable implements the interface Microsoft.SqlServer.Dts.Runtime.Wrapper.Variable which has no GetSensitiveValue method defined.
Let's assume the connection string is a project parameter for now.
Despite the lack of a GetSensitiveValue method existing in the Script Component, I was able to access the value just fine.
What I did fumble with was my Package Protection level and how it interacts with Project Parameters that are marked as Sensitive.
I defined a Project Parameter named MySecretPassword and populated it with SO_71308161 and marked it as sensitive.
Script Source
I defined a single column output and my intention was to just push the password into the dataflow to confirm I was able to access it
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public string MySecret;
public override void PreExecute()
{
base.PreExecute();
MySecret = Variables.MySecretPassword;
}
public override void CreateNewOutputRows()
{
Output0Buffer.AddRow();
Output0Buffer.Column = this.MySecret;
}
}
I then routed the data to a derived column and dropped a data viewer between the two. My code did not throw an exception but it did show an empty string.
If I tried to access my sensitive parameter value in a script task using myVariable.Value it would throw an error as expected but I was getting my sensitive value back.
Package Protection Level
I love StackOverflow questions that teach me things. My default mode is to define projects that use a Project & Package protection level of DontSaveSensitive. Which is incompatible with using Sensitive project parameters. Not incompatible in that it will throw an exception, but when you run the package, accessing that value will be blanked out (for strings at least).
As soon as I change the Project and then Package's protection level to EncryptSensitiveWithUserKey (or anything that isn't DontSaveSensitive), both the Script Task's .GetSensitiveValue() and the Script Component's Variables.MySecretPassword worked.

Class Library Localization in Windows Universal / Store App

I have a solution with a Windows Store app project and a Class Library project and I want to add Localization support.
How can I add the all the Resource files to my Class Library and use them in both my App and Class Library?
In order to avoid writing a lot of boilerplate and error prone code when you add a new resource string like:
Add it to .resw file
Add it to your Static class that provides access to the resource
Add it to each language specific .resw file (ex: en, fr, pt, etc)
You can use the following approach:
Create "Strings" folder and add there just one folder for default language (for example "en-US") in your Class Library
Add Resources.resw file to "en-US" folder with required keys/values
Install Multilingual App Toolkit
Enable MAT in VS for your Class Library (VS->Tools->Enable Multilingual App Toolkit)
Add required languages to your Class Library (VS->Project->Add Translation languages...)
Install ResW File Code Generator VS extension
Go to Resources.resw file properties and set Custom Tool to "ReswFileCodeGenerator" (you can also specify namespace in Custom Tool Namespace)
To solve issue with supported languages detection(currently generated manifest contains supported languages according to folder structure "Strings/en-US") you need to add folders for all required languages in your App library ("fr-FR", "bg-BG", etc) and put Resources.resw file with only one fake key.
Build your solution and enjoy!
With this approach all your resources are available via static class generated by ReswFileCodeGenerator and all of them work with x:uid in XAML. You don't need to care about keys synchronization between different languages. Also MAT can translate your resources for you.
Ok, I found how to do this and with a sample project found here
Basically the implementation is the following:
In the ClassLibrary create a folder named "Strings"
Inside the Strings folder create one for each language (ex: en, fr, pt, etc)
And add a Resources.resw in each of those folders with your keys/values
Now add a new Class in your ClassLibrary that has the following code(adapted to your project):
using System;
using Windows.ApplicationModel.Resources;
namespace MyClassLibraryName.Tools {
public static class LocalizationTool {
static ResourceLoader resourceLoader = null;
public static string MyStringOne {
get {
String name;
GetLibraryName("MyStringOne", out name);
return name;
}
}
private static void GetLibraryName(string resourceName, out string resourceValue) {
if(resourceLoader == null) {
resourceLoader = ResourceLoader.GetForCurrentView("MyClassLibraryName/Resources");
}
resourceValue = resourceLoader.GetString(resourceName);
}
}
}
And in your ClassLibrary or MainApp just call the following:
string text = LocalizationTool.MyStringOne;

Cannot implicitly convert type (linq to entity)

I am working on a mvc5 project and I connected my database with Linq to Entity but for some reasons I had to delete .edmx file and reconnect my databse in aother folder.
Since that time I am facing an error :
"Cannot implicitly convert type 'TicketingDemoProject.Models.User' to
'TicketingDemoProject.User'.
I know the folder is not same but don't know how to reslove this issue.
Thank you for your help.
code :
namespace TicketingDemoProject.Controllers{
public class TechnicianController : Controller{
private TicketingDBENtities tickets = new TicketingDBEntities();
public ActionResult Index(){
string username = User.Identity.name;
User u = tickets.User.Single(user1=>user1.user_name == username)
int userIdenti = u.User_Id;
}
}
}
By changing the folder, you changed the namespace for your edmx generated classes. Visual studio by default will use the namespace based on the current folder name. You can modify your namespace for edmx to your previous one which is TicketingDemoProject.
To change the namespace:
Right click on edmx file go to properties
Specify Custom Tool Namespace (Specify your new name space TicketingDemoProject). By default it would be empty, which means that it will have the default namespace generated by the visual studio based on the folder name.
Your code is using previously generated classes, which were in namespace TicketingDemoProject now since you changed the folder and generated edmx in Model, the namespace associated with the edmx's classes is TicketingDemoProject.Models and hence the error.
To see how Visual Studio manages the namespace see: Understanding Visual Studio's Default Namespaces

Categories