Is DataContractSerialization broken on mono? - mono

This code runs without problem on .net, but crashes when using mono 4.4.1
#I __SOURCE_DIRECTORY__
#r "System.dll"
#r "System.Net.Http.dll"
#r "System.Runtime.Serialization"
open System
open System.Net.Http
open System.IO
open System.Text
open System.Runtime.Serialization
open System.Runtime.Serialization.Json
[<DataContract(Name="request")>]
[<CLIMutable>]
type Request =
{
[<field: DataMember(Name = "act")>]
Action: string
[<field: DataMember(Name = "qry")>]
Query: obj
}
let fromJson<'T> (json: string) =
let dcs = DataContractJsonSerializer(typeof<'T>)
use ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(json))
(new StreamWriter(ms)).Write(json)
dcs.ReadObject(ms) :?> 'T
let toJson o =
let dcs = DataContractJsonSerializer(o.GetType())
use ms = new MemoryStream()
dcs.WriteObject(ms, o)
ms.Position <- 0L
(new StreamReader(ms)).ReadToEnd()
{ Action = "Test"; Query = new Object() }
|> toJson
|> printfn "%s"
This is a minimal failing test, just throw it to the fsharpi and compare it with the fsi result.
Actually this alone triggers the error:
let test = { Action = "Test"; Query = new Object() }
let dcs = DataContractJsonSerializer(test.GetType())
use ms = new MemoryStream()
dcs.WriteObject(ms, test)

Related

Index Out of Bound exception while rendering RDLC Reports in ASP.NET Core

My ASP.NET Core MVC project has several reports. To render the reports as PDF, I'm using AspNetCore.Reporting library.
This library works fine for a single report but due to some cache issues it throws an exception while generating another report. The solution I found on the internet was to run report generation as a new process but I don't know how to implement that.
I found the suggestion to use Tmds.ExecFunction to run report generation as a seperate process. But I dont know how to pass parameters to the function.
Here is my code:
string ReportName = "invoiceDine";
DataTable dt = new DataTable();
dt = GetInvoiceItems(invoiceFromDb.Id);
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("bParam", $"{invoiceFromDb.Id}");
param.Add("gParam", $"{salesOrderFromDb.Guests}");
param.Add("tParam", $"{invoiceFromDb.Table.Table}");
param.Add("dParam", $"{invoiceFromDb.Time}");
param.Add("totalP", $"{invoiceFromDb.SubTotal}");
param.Add("t1", $"{tax1}");
param.Add("t2", $"{tax2}");
param.Add("tA1", $"{tax1Amount}");
param.Add("tA2", $"{tax2Amount}");
param.Add("AT1", $"{totalAmountWithTax1}");
param.Add("AT2", $"{totalAmountWithTax2}");
param.Add("terminalParam", $"{terminalFromDb.Name}");
param.Add("addressParam", $"{t.Address}");
param.Add("serviceParam", "Service Charges of applicable on table of " + $"{personForServiceCharges}" + " & Above");
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
return File(result,"application/Pdf");
This is my version of the function:
``` public byte[] GenerateReport(string ReportName, Dictionary<string,string> Parameters,string DataSetName,DataTable DataSource )
{
string guID = Guid.NewGuid().ToString().Replace("-", "");
string fileDirPath = Assembly.GetExecutingAssembly().Location.Replace("POS_Website.dll", string.Empty);
string ReportfullPath = Path.Join(fileDirPath, "\\Reports");
string JsonfullPath = Path.Join(fileDirPath,"\\JsonFiles");
string rdlcFilePath = string.Format("{0}\\{1}.rdlc", ReportfullPath, ReportName);
string generatedFilePath = string.Format("{0}\\{1}.pdf", JsonfullPath, guID);
string jsonDataFilePath = string.Format("{0}\\{1}.json", JsonfullPath, guID);
File.WriteAllText(jsonDataFilePath, JsonConvert.SerializeObject(DataSource));
FunctionExecutor.Run((string[] args) =>
{
// 0 : Data file path - jsonDataFilePath
// 1 : Filename - generatedFilePath
// 2 : RDLCPath - rdlcFilePath
ReportResult result;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding.GetEncoding("windows-1252");
LocalReport report = new LocalReport(args[2]);
DataTable dt = JsonConvert.DeserializeObject<DataTable>(File.ReadAllText(args[0]));
report.AddDataSource(args[3], dt);
result = report.Execute(RenderType.Pdf, 1,Parameters);
using (var fs = new FileStream(args[1], FileMode.Create, FileAccess.Write))
{
fs.Write(result.MainStream);
}
}, new string[] {jsonDataFilePath, generatedFilePath, rdlcFilePath, DataSetName });
var memory = new MemoryStream();
using (var stream = new FileStream(Path.Combine("", generatedFilePath), FileMode.Open))
{
stream.CopyTo(memory);
}
File.Delete(generatedFilePath);
File.Delete(jsonDataFilePath);
memory.Position = 0;
return memory.ToArray();
}
But it throws exception "Field marshaling is not supported by ExecFunction" on line:
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
No Need to run report generation as a seperate process. Just Dont Pass extension as 1
in:
var result = localReport.Execute(RenderType.Pdf, 1, param);
The Solution is:
int ext = (int)(DateTime.Now.Ticks >> 10);
var result = localReport.Execute(RenderType.Pdf, ext, param);

CodeDom referencing System.Management

No matter what I try I am unable to reference System.Management in to my codedom project, I have tried
Dim assemblyReferences = New String() {"System.Drawing.dll",
"System.Data.dll",
"System.Data.DataSetExtensions.dll",
"System.Deployment.dll",
"System.Management.dll",
"System.Net.dll",
"System.Net.Http.dll",
"System.dll",
"System.Core.dll",
"mscorlib.dll",
"System.Windows.Forms.dll",
"System.Xml.dll",
"System.Xml.Linq.dll"}
param.ReferencedAssemblies.AddRange(assemblyReferences)
Among other methods such as using it implicitly and importing it at the top of the class
I have found it to work using both...
var compileUnit = new CodeCompileUnit();
compileUnit.ReferencedAssemblies.Add("System.dll");
compileUnit.ReferencedAssemblies.Add("System.Management.dll");
...and...
var parameters = new CompilerParameters(new string[] {"System.dll", "System.Management.dll" }, "TestAssembly.dll", true);
var results = provider.CompileAssemblyFromDom(parameters, compileUnit);
System.dll is required by System.Management.dll
The code snippet I used was:
var compileUnit = new CodeCompileUnit();
compileUnit.ReferencedAssemblies.Add("System.dll");
compileUnit.ReferencedAssemblies.Add("System.Management.dll");
var codeNamespace = new CodeNamespace("ClassLibrary1");
compileUnit.Namespaces.Add(codeNamespace);
var testClass = new CodeTypeDeclaration("TestClass");
var declaration = new CodeMemberField(typeof(System.Management.ManagementClass), "managementClass");
testClass.Members.Add(declaration);
codeNamespace.Types.Add(testClass);
I compiled it with:
using (var provider = CodeDomProvider.CreateProvider("VisualBasic"))
{
var parameters = new CompilerParameters(new string[] {"System.dll", "System.Management.dll" }, "TestAssembly.dll", true);
var results = provider.CompileAssemblyFromDom(parameters, compileUnit);
return results;
}
Sorry the example is in C#.

EPPPlus cannot open RDLC rendered to EXCELOPENXML

Does anyone have any idea , or even a solution, to open an xlsx file using EPPlus created from an rdlc report.
At the moment, when I try to do this I get an null exception when I try to access the worksheets.
// filename is the xlsx file created by exported rdlc to excel
FileInfo newFile = new FileInfo(filename);
ExcelPackage pck = new ExcelPackage(newFile);
// I get error here
pck.Workbook.Worksheets.Add("New Sheet");
If you intention is to add onto the file you are using the wrong constructor. The one you are using now is for creating a new package off of a template. The on your want is this (without the extra Boolean) which will open the file directly:
ExcelPackage pck = new ExcelPackage(newFile);
Response to Comments
#A.Ellwood I just tried it with the file you posted and it works fine for me. Here is the code I used:
[TestMethod]
public void RDLC_Test()
{
var datatable = new DataTable("tblData");
datatable.Columns.AddRange(new[]
{
new DataColumn("Col1", typeof (int)), new DataColumn("Col2", typeof (int)),
new DataColumn("Col3", typeof (object))
});
for (var i = 0; i < 10; i++)
{
var row = datatable.NewRow();
row[0] = i;
row[1] = i*10;
row[2] = Path.GetRandomFileName();
datatable.Rows.Add(row);
}
var fi = new FileInfo(#"c:\temp\Report1.xlsx");
using (var pck = new ExcelPackage(fi))
{
var workbook = pck.Workbook;
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cells.LoadFromDataTable(datatable, true);
pck.Save();
}
}

how can I query for releases / iterations via rally c# api?

I am trying to query on both Release and Iteration so I can fill out a drop down list with these various values. I'm not quite sure how to do this, however. What are the members of the object that come back via the query if we are able to do this? (Name, FormattedID, CreationDate, etc). Do we just create a new request of type "Release" and "Iteration" ?
Thanks!
Here is a code that queries on releases based on a project reference. If this project is not in a default workspace of the user that runs the code we either need to hardcode the workspace reference or get it from the project.
class Program
{
static void Main(string[] args)
{
RallyRestApi restApi;
restApi = new RallyRestApi("user#co.com", "TopSecret1984", "https://rally1.rallydev.com", "1.40");
var projectRef = "/project/22222222"; //use your project OID
DynamicJsonObject itemWorkspace = restApi.GetByReference(projectRef, "Workspace");
var workspaceRef = itemWorkspace["Workspace"]["_ref"];
Dictionary<string, string> result = new Dictionary<string, string>();
try
{
Request request = new Request("Release");
request.ProjectScopeDown = false;
request.ProjectScopeUp = false;
request.Workspace = workspaceRef;
request.Fetch = new List<string>()
{
"Name"
};
// request.Query = new Query("Project.ObjectID", Query.Operator.Equals, "22222222"); //also works
request.Query = new Query("Project", Query.Operator.Equals, projectRef);
QueryResult queryResult = restApi.Query(request);
foreach (var r in queryResult.Results)
{
Console.WriteLine("Name: " + r["Name"]);
}
}
catch
{
Console.WriteLine("problem!");
}
}
}
}

Mono.Security.Cryptography RijndaelManaged class issue using CFB-8 mode

I'm writing to report about cryptography issue. The problem happens using RijndaelManaged class from the System.Security.Cryptography. It is important for me to use RijndaelManaged with CFB-8 (FeedbackSize = 8) mode without padding (PaddingMode.None). Such settings configuration makes encrypted data size equal to the decrypted data size.
Unfortunately Mono (Mono Compiler for MVS2010 IDE v2.0.8152) compiled code throws exception on data encryption with message:
[Unhandled Exception: System.Security.Cryptography.CryptographicException: invalid block length at Mono.Security.Cryptography.SymmetricTransform.FinalEncrypt].
I made tests with the .NET framework 4.0 under Windows XP and Windows 7, using the native Visual Studio 2010 compiler. I found that the native Microsoft .NET compiler does not throw any exceptions, and the code example works well.
Below I have pasted two examples (Repro code), one for Mono which throws an exception and one for native C# compiler in this case there are no exceptions. Also I have also pasted links to online compilers to test the code.
Why is the Mono Compiler throwing this exception?
Mono code Sample (Online compiler for testing, Compile Online)
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Dela.Mono.Examples
{
public class HelloWorld
{
public static void Main(string[] args)
{
string plainText = "This will be encrypted.";
string plainText2 = "";
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.BlockSize = 128;
aesAlg.KeySize = 256;
aesAlg.Mode = CipherMode.CFB;
aesAlg.FeedbackSize = 8;
aesAlg.Padding = PaddingMode.None;
aesAlg.GenerateKey();
aesAlg.GenerateIV();
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
MemoryStream msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
swEncrypt.Write(plainText);
}
}
Console.WriteLine(msEncrypt.ToArray().Length);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
byte[] customArray = msEncrypt.ToArray();
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
MemoryStream msDecrypt = new MemoryStream(customArray);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
plainText2 = swDecrypt.ReadToEnd();
}
}
Console.WriteLine(plainText2.Length);
Console.WriteLine(plainText2);
}
}
}
Native C# Code Sample (Online compiler for testing, Compile Online)
// Rextester.Program.Main is the entry point for your code. Don't change it.
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
string plainText = "This will be encrypted.";
string plainText2 = "";
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.BlockSize = 128;
aesAlg.KeySize = 256;
aesAlg.Mode = CipherMode.CFB;
aesAlg.FeedbackSize = 8;
aesAlg.Padding = PaddingMode.None;
aesAlg.GenerateKey();
aesAlg.GenerateIV();
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
MemoryStream msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
swEncrypt.Write(plainText);
}
}
Console.WriteLine(msEncrypt.ToArray().Length);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
byte[] customArray = msEncrypt.ToArray();
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
MemoryStream msDecrypt = new MemoryStream(customArray);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
plainText2 = swDecrypt.ReadToEnd();
}
}
Console.WriteLine(plainText2.Length);
Console.WriteLine(plainText2);
}
}
}
The bug was fixed. The sources can be taken from the mono GIT repository.
master: e094d3dc0cf186f1de32d5340d847dc18aeca0e2
mono-2-10: 98e4842eb19dfd60000ada19e9bfb265fad7c84b