Custom c# code in a Report - c#

I am populating a report using an Object. Everything works fine, if my members are string, however, I have a few members, which are List<string>.
When I add these fields to the report (in designer, visual studio 2012) and run the report, they show as
'#Error'
Viewing the properties of the report, I can see that there is a 'custom code' tab, for which I've entered the following method to convert the list of strings into a array of string.
public string[] GetListItems(List<string> intList)
{
var s = intList.ToArray();
return s;
}
Then when I try and replace the field with an expression and enter the following:
=Join(Code.GetListItems(Fields!Aka.Value),",")
and then run the report, VS fails to build with the following:
Error 2 The Value expression for the textrun ‘Aka.Paragraphs[0].TextRuns[0]’ contains an error: [BC30456] 'GetListItems' is not a member of 'ReportExprHostImpl.CustomCodeProxy'.
Error 1 There is an error on line 0 of custom code: [BC30183] Keyword is not valid as an identifier.
Can anyone shed any light why this is?

That is C# code. Directly in the report you can only use Visual Basic. C# is avaliable as an external DLL.

For those who can't create go through the difficulties of implementing a third-party DLL. A simpler; but, a messier solution is as follows.
To summarize solution, you can create properties that returns a value that the reports can easily work with.
In my scenario, I had 2 classes:
public class Parent {
public Child { get; set; }
}
public class Child {
public string Name { get; set; }
}
The type that I was binding to my Report was Parent; however, I needed to access the Name property inside Child. In otherwords I needed to do:
Parent.Child.Name
This where I ran into the same problem that the OP ran into. Due to the scope of my project (a college project), I can't bother with third-party dlls or writing my own dll...
So what I did is add more properties to the Parent class.
public class Parent {
public Child { get; set; }
public string ChildName { get => Child.Name; }
}
public class Child {
public string Name { get; set; }
}
By adding an additional property to Parent that has an type that Reports can work with, I can now easily access the Child's Name through my Parentclass.
Of course this is messy; but, I'm in a situation where I can't go with the more complicated/time consuming dlls solution.
I just hope my instructors will allow this solution without penalty...

If you just created a report and showing an error code like
BC30016 labels are not valid outside of the method.
The reson in my case was that i have insert the random numerical value n the code property of a report1.rdlc
Hence to solve this type of error, goto report properties and remove the value from the code.

Related

Dynamic LINQ with Skip and Take causes Exception: Unknown LINQ expression of type 'Dynamic'

I'm building a report builder/runner using System.Linq.Dynamic.Core (1.2.20) in an ASP.NET MVC (5.2.9) app and I mostly have it working, except for one annoying issue. I can't get Skip and Take to work. Basically my code is doing this:
_context.SetDynamic("ENTITY_NAME")
.Where(_parsingConfig, WHERE_EXPRESSION)
.OrderBy(_parsingConfig, ORDER_BY_EXPRESSION)
.Skip(???)// exception
.Take(???)// exception
.Select(_parsingConfig, SELECT_EXPRESSION)
.ToDynamicListAsync();
Running that causes this exception:
Unknown LINQ expression of type 'Dynamic'.
When I remove Skip and Take then it works correctly and I see the results, but I lose out on the paging capabilities.
From what I can tell, it has to do with me starting out with SetDynamic which returns an IQueryable<object>. Elsewhere in the app I do the same query, but start out from a Set<T> and there's no problems with it.
What should I do to get Skip and Take to work?
After some more trial and error I got it to work. I manually tested switching to Set(Type) to see if it fixed Skip and Take and it did.
From there I decided to change the model for Report to contain a string Object property. It already had an ObjectType property which was an enum, but I decided to replace it with a string, and I'll probably do that everywhere else I use it and just remove it.
After that, using reflection I got all objects in the DbContext assembly that implement a marker interface called IEntity and projected them into an IList<Entity>:
public sealed class Entity {
public string DisplayName { get; set; }
public string Name { get; set; }
public Type Type { get; set; }
}
... and then stored them as a singleton for dependency injection. In the report runner class since I already know the report Id I just pull it out of the database and then pull out the Entity where Report.Object == Entity.Name from the list and pass the type off to Set(Type).
Kind of long winded, but it works. I had been planning to have something like that list for a little while so I can present it as drop down list when a new report is being created so the report runner knows where to start from when building the query.

Workaround for Compiler Error CS0542: member names cannot be the same as their enclosing type

I've got a fairly large VB.NET project that was built by a former employee. He got most of it working, but not all of it.
It has been running like this for 2 years, I know. Perhaps 3.
Now, Management is pushing to get this project revived and finish up what was never done.
The project has been assigned to me, and I have been given a month to get up to speed on it.
I am re-writing it in C#, because my coding is stronger in that language.
One of the good ideas he used was to structure the class so that they mimicked the database tables:
table name becomes class name
column names become property names
column datatypes become property datatypes
Here is one small example:
Public Class Acct_Code
Private _Acct_Code_ID As String = String.Empty
Private _Acct_Code As String = String.Empty
Public Property Acct_Code_ID() As String
Get
Return _Acct_Code_ID
End Get
Set(ByVal value As String)
_Acct_Code_ID = value
End Set
End Property
Public Property Acct_Code() As String
Get
Return _Acct_Code
End Get
Set(ByVal value As String)
_Acct_Code = value
End Set
End Property
End Class
Currently, I cannot put this VB code in C# because of Error CS0542 that says:
Error Message
'user-defined type' : member names cannot be the same as their enclosing type
A name was used more than once in the same construct. This error might be caused by inadvertently putting a return type on a constructor.
I understand either the class or the property should be renamed; however, I would like to get this project working piece at a time instead of being over here creating code that will not work at all.
Does anyone know of a way to work around this compiler error - just temporarily until I get the project built?
I know there are ways to ignore warnings and ignore exceptions, but I don't know a way to ignore a compiler error.
To work around the compiler error, just split your class into a base class and a derived class and then move the offending members into the base class.
class A
{
public string B { get; set; } // <-- This compiles just right!
}
class B : A
{
}
You can't ignore a violation of the rules of the language. You must fix the names.
You may well want to try to fix the names in VB before porting, as then you can have a working codebase at all times... which will allow you to take advantage of refactoring. Then when you're sure that all the member names are different from the type names, you can port to C#.
As an aside, when you port that code you should take advantage of automatically implemented properties, leaving:
public class Account
{
public string Id { get; set; }
public string Code { get; set; }
}
(Then try to move away from allowing objects to mutate in all possible ways... that's a different matter :)

Change Info Shown in VS 2010 DataTip

I am attempting to find a way to alter the information that is shown in a DataTip in the VS 2010 Debugger. The purpose being that I would like to choose what property value is shown on the initial window of a DataTip.
For example, when hovering over a collection in debug mode I am presented with the Name of the collection followed by its Count property's value.
This is useful information, but when I am hovering over one of my custom objects I am only presented with a path providing the type of object it is (in my case something like BOS.SuggestedOrdersDataEntity.SuggestedOrdersEntity).
I would like to have this initial DataTip window contain the property that I would determine to be the most useful depending on what custom object it is. For instance it could be the case that for an object that is of type SuggestedOrdersEntity it would be more helpful for the DataTip to show the value of its VendorName property in place of BOS.SuggestedOrdersDataEntity.SuggestedOrdersEntity (similar to the way collections show their Count property). The goal is to not have to use the '+' expander to find the current value of the VendorName (or whatever property is most useful).
I would like to be able to alter the DataTips so that I can customize them to immediately show a specific property's value (just like Count shows for collections) without needing to expand and view all the properties.
Does anyone know if this is possible? I've done some researching on DataTips, but nothing I have found discusses customizing them in this way...
You can use the DebuggerDisplay attribute, examples here.
[DebuggerDisplay("{Name} - {StockSymbol}")]
public class Company
{
public string Name { get; set; }
public string StockSymbol { get; set; }
public IEnumerable<Employee> Employees { get; set; }
public Company(string name) { Name = name; }
}

Compile Time Type Assignment

I'm working on a custom validation framework for my WPF/C# application.
What I'm looking to do is to retrieve strings from the resource file where the viewmodel is declared, but in the actual validation code it self. This particular string is the same resource used by label on the editing UI Form.
My code works fine with the following syntax -
[Required(TypeRes = typeof(Resources))]
public string RequiredStringWithDesc { get; set; }
But what I"m looking for is something that is syntacticly cleaner looking. I was trying to use
const Type LocalRes = typeof(Resources);
[Required(TypeRes = LocalRes)]
public string RequiredStringWithDesc { get; set; }
Any suggestions on a simpler syntax? The old c++ DEFINE statement here would work well.
FYI: the reasons for going to this much work has to do with how we are doing localization and UI construction.
EDIT To answer a couple of questions about why are we doing this?
We are going to be using the same string from the resource file to -
On the edit screen, this is the label to identify the field.
In the datamodel, if there is a validation error, we are using this to correctly label the problem in the log file.
In the Viewmodel, we are reusing this label in the validation error message to reinforce where the problem is to the user.
This is part of a real time inspection system and some of the failure modes relate directly back to these data fields. So we can easily get the correctly localized label to apply to run-time fault messages
The general concept is that this simplifies presenting consistent messages to the user while only creating things once. With regards to validation attributes (and this question), we need to be able to get the Resource file type to load the correct message.
Create a new attribute class which inherits from the RequiredAttribute and set default values.
public class LocalizedRequiredAttribute : RequiredAttribute {
public LocalizedRequiredAttribute() { /* TypeDef = typeof(Resources);*/ }
}
public class MyModel {
[LocalizedRequired]
public string RequiredStringWithDesc { get; set; }
}

Data Binding of Computed Properties in Entity Framework

I am trying to find an effective way to databind computed fields of an Entity Framework model in winforms. I am using Visual Studio 2008 and .NET framework 3.5. An example would be for EntityX, say I have columnA and columnB, and I want a computed property named sumAB. The way I have been doing this has been with partial classes:
public partial class EntityX
{
public int sumAB
{
get
{
return this.columnA + this.columnB;
}
}
}
I then am using visual studio to add EntityX as a data source, so I can use the automatic drag and drop data binding. The issue that I am having is that the computed properties are not appearing under the Data Source fields. I am looking for a way to have the automatic databinding of computed fields.
I know I could do this manually, but then I would have to also manually write all of the binding code to refresh the field when columnA or columnB are changed. I also do not have access to make this field computed on the SQL server side either.
Does anyone know of any ways to accomplish this or any other similar directions to persue?
Thanks!
UPDATE
I tested this on another machine, using Visual Studio 2010 and .NET 4, and I am still receiving the same behavior. Interestingly, I can manually create a textbox and add a databinding, and it will work fine, as below:
sumABTextBox.DataBindings.Add(
new System.Windows.Forms.Binding("Text", EntityXBindingSource, "sumAB", true));
It also worked if I placed the property in the .edmx file, but this is not desirable, as it will be wiped any time the database is updated.
Any other ideas?
UPDATE 2
Still no solution... I had to use alternatives in my code to meet deadlines. I am still very interested in this if anyone finds an answer...
Sounds strange to me. Because I use the same approach in my project (Entity Framework, Self Tracking Entities, WCF, Winforms).
I constructed a simple winforms applciation to test it and the "computed" property just shows up in the databindings.Text property of a textbox control.
I created a simple class:
public partial class Test
{
public int A { get; set; }
public int B { get; set; }
public Test()
{
}
}
public partial class Test
{
public int AB
{
get { return A * B; }
}
}
Added a bindingsource to a form (with datasource pointing to an object of type Test) and three textboxes binded to the bindingsource and the properties: A, B and AB. In the constructor of the form I created an instance of test, populated values for A and B, set bindingsource.DataSource to the created instance and thinks were groovy on the form ;)
This simple test case would be no different from your situation, other than that you work with entities which are off-course just Objects. I really can't see the problem from your description...Any further comments could help me help you further...
I basically just asked the same question (WPF not WinForms) yesterday - Show Computed Property in Entity Framework and WPF UI .
In short, I couldn't find any automatic support. I had to create the columns in my DataGridView for each computed property. Then, to let the DataGridView know that those properties have updated, I have to call OnPropertyChanged("ComputedPropertyName") in the OnChanged partial method.
e.g.
public partial class Test
{
public int AB
{
get { return A * B; }
}
public partial void OnAChanged()
{
OnPropertyChanged("AB");
}
public partial void OnBChanged()
{
OnPropertyChanged("AB");
}
}
If there is an automatic way for this to work, I would like to know too.

Categories