How to register Automapper into vb.net global.asax file? - asp.net

I've a ASP.NET API Version 2.0 with VB.Net in back end where I'm trying to initialize Automapper in Global.asax file. Here, I'm using Auto Mapper version 5.2. I can initialize using the C# code but I am not so sure about the VB.Net. After googling I've found something and here is what I'm trying now:
Module AutoMapperConfiguration
Public MapperConfiguration As IMapper
Public Sub Configure()
Dim config = New MapperConfiguration(//in this line I'm getting an error:
Overload resolution failed because no accessible 'New' can be called with these arguments: 'Public Overloads Sub New(configurationExpression As MapperConfigurationExpression)': Lambda expression cannot be converted to 'MapperConfigurationExpression' because 'MapperConfigurationExpression' is not a delegate type.
Sub(cfg)
cfg.AddProfile(New EntityMapProfile())
End Sub)
MapperConfiguration = config.CreateMapper()
End Sub
End Module
Then I've called this module from the Application_Start()
AutoMapperConfiguration.Configure()
But last time I've done this using C# with the following line of code in the global.asax file
Mapper.Initialize(x =>
{
x.AddProfile<EntityMapProfile>();
});
Under Application_Start() which worked nicely but now even if I convert those above lines of code then still I'm facing issues. I would appreciate your help or suggestion on the above.

For whatever reason VB.NET is not using the correct constructor when you inline the Sub for the Action.
Module AutoMapperConfiguration
Public MapperConfiguration As IMapper
Public Sub Configure()
Dim configAction As Action(Of IMapperConfigurationExpression) = Sub(cfg) cfg.AddProfile(Of EntityMapProfile)()
Dim config = New MapperConfiguration(configAction)
MapperConfiguration = config
End Sub
End Module
The above will force your lambda to the correct type of Action(Of IMapperConfigurationExpression) and thereby force VB.NET to use the correct constructor overload.

Related

Serilog is missing log file entries for my ASP VB.NET web project

The following code works fine for one user on the web site.
However as soon an multiple users start logging in simultaneously, Serilog starts missing log file entries. Anybody know what I am missing please?
Public Class cLogger
Public Shared gSerilogger As ILogger = Nothing
Public Shared gblSeriLock As New Object
Public Shared Sub DoSerilog(ByVal sLogMessage As String)
SyncLock gblSeriLock
If gSerilogger Is Nothing Then
gSerilogger = New LoggerConfiguration().WriteTo.Console().WriteTo.File("d:\Logfiles\SERI.log").CreateLogger()
End If
gSerilogger.Information(sLogMessage)
End SyncLock
End Sub
End Class
Usage example:
cLogger.DoSerilog("Test")

Website - The type initializer for 'Static Class' threw an exception

I have a VB.NET website project. In one of the pages, during a button click, it is supposed to load a telerik RadGrid with data. It works fine on my local machine. However when I deploy it to pre-production on a server, it throws the following error.
The type initializer for 'Utility' threw an exception
Utility is a Static class and while calling any members of the static class (either public static functions or public static variables) I was receiving this error.
Here is the code snippet:
Partial Class Session
Inherits System.Web.UI.Page
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim testString As String = String.Empty
Dim encryptString As String = String.Empty
Try
encryptString = Utility.EncryptString(cellValue.ToString())
testString = Utility.test
Catch ex As Exception
Logger.getInstance().log("Value1" & cellValue.ToString() & "Value2" & testString)
Finally
End Try
End If
End Sub
End Class
In my Utility.vb, this is what I have:
Public Class Utility
Public Shared test As String = "hello"
Public Shared Function EncryptString(ByVal strEncrypted As String) As String
Try
Dim b As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(strEncrypted)
Dim encryptedConnectionString As String = Convert.ToBase64String(b)
Return encryptedConnectionString
Catch ex As Exception
Logger.getInstance().log("Error occurred in Utility.vb while executing EncryptString method. \nSOURCE: " & ex.Source.ToString() & "\nMESSAGE: " & ex.Message.ToString() & "\nTARGETSITE: " & ex.TargetSite.ToString() & "\nSTACKTRACE: " & ex.StackTrace.ToString())
Logger.getInstance().log("\nstrEncrypted: " & strEncrypted)
Finally
End Try
End Function
End Class
From my logging statements, I realized that the error is happening right when I call the Utility class because none of the logging statements I added into the EncryptString() function are being shown in my logs.
I tried commenting out the code for EncryptString() function and added just a public static string variable called test in my Utility class, and tried accessing it from my code from Session.aspx.vb. That string value was not being returned as well.
By the way, all of my code is in the same website project. The error is driving me crazy for past 2 days. Like I mentioned, it works fine on my local machine, but fails only on the pre-prod server. The code was written using an older framework (3.5 I believe) and then we upgraded to 4.6.2 and migrating to new servers. We are facing this issue during the migration process on the new server.
OK, so I figured out the issue. At the beginning of the Utility.vb class there were some unsupported cryptographic algorithm variable declarations.
Private Shared DES As New TripleDESCryptoServiceProvider
Private Shared MD5 As New MD5CryptoServiceProvider
FIPS compliance is turned on, on the server and we already knew these algorithms were non-compliant with the latest .net frameworks. But I didn't realize even just these declarations would throw a misleading error, when they were not really being used in my function calls.
When I commented out those parts of the code, it started working fine.
Check the InnerException property of the exception. Any time a class initializer fails the original exception should be set as the InnerException property of the unhandled exception.
If you want a truly static class, you need to make it a module, in VB.Net.

How to set connection string in Linq to SQL constructor

Im trying to set a connection string for a my data access layer which is using a value from my Web.Config file from another project.
I create a new class library and add a dbml (Linq to SQL) file and drag a table.
I then add this code to the code file
Partial Public Class MyDataContext
Public Sub New()
MyBase.New(ConfigurationManager.ConnectionStrings("WebConnectionString").ConnectionString, mappingSource)
OnCreated()
End Sub
End Class
This gave me an error "'Public Sub New()' has multiple definitions with identical signatures."
I understood what the error means so did a quick search on a way around it as when i recompiled the project the same problem remained. The way to approach this was/is to override the OnCreated method so i changed the code to:
Private Sub OnCreated()
Me.New(ConfigurationManager.ConnectionStrings("WebConnectionString").ConnectionString, mappingSource)
End Sub
This gave the error "Constructor call is valid only as the first statement in an instance constructor" but not a lot of ways to overcome it (well i see a few C# examples but im sure im an converting it to the correct VB .Net code)
After further research no matter what i do, i dont seem to be able to set the connection string in my DAL which should be using the Web.Config connection string value from another project.
What could i be doing wrong?
OK, In C# first:
partial class MyDataContext
{
public static MyDataContext Create()
{
return new MyDataContext(ConfigurationManager.ConnectionStrings("WebConnectionString").ConnectionString,
mappingSource);
}
// etc
}
Now, my attempt to translate that in VisualBasic.NET
Partial Public Class MyDataContext
Public Shared Function Create() as MyDataContext
return New MyDataContext (ConfigurationManager.ConnectionStrings("WebConnectionString").ConnectionString,
mappingSource)
End Function
End Class
Called via:
Dim db as MyDataContext = MyDataContext.Create()

Getting a ScriptReference from a ScriptResourceMapping definition in a custom control

I am building a custom control with client side scripts that I would like to reference using ScriptManager.ScriptResourceMapping (to make use of the Path and DebugPath attributes).
I would like the custom control to be easily ported to other projects - i.e. I would like to drag and drop the codebehind files (and eventually make the control a separate DLL, but for now the drag and drop will suffice). I would therefore like to avoid (1) having the client script as an embedded resource, (2) referenced as a WebResource in the AssemblyInfo, or (3) have the ScriptManager.ScriptResourceMapping.AddDefinition in global.asax.
In simple terms can I get the script management code to be in just the custom control's code?
At the moment I am getting an error stating that the script reference cannot be found in the assembly, and I guess I am setting the wrong assembly.
My custom control code is as follows:
Public Class MyControl
Inherits System.Web.UI.LiteralControl
Implements ISectionControl, IScriptControl
Private _scriptReference As ScriptReference
Public Sub New()
' Add the resource mapping
ScriptManager.ScriptResourceMapping.AddDefinition("MyControlScript", New ScriptResourceDefinition With {
.ResourceAssembly = System.Reflection.Assembly.GetExecutingAssembly,
.ResourceName = "MyControlScript.js",
.Path = "Path.To.MyControlScript.minimised.js",
.DebugPath = "Path.To.MyControlScript.original.js"
})
' Set the script reference
_scriptReference = New ScriptReference("MyControlScript.js", Assembly.GetExecutingAssembly.FullName)
End Sub
Protected Overrides Sub OnPreRender(e As System.EventArgs)
MyBase.OnPreRender(e)
' Register the script
ScriptManager.GetCurrent(Page).RegisterScriptControl(Of MyControl)(Me)
' Some code to set the Text of the literal control
' ...
End Sub
Public Function GetScriptDescriptors() As System.Collections.Generic.IEnumerable(Of System.Web.UI.ScriptDescriptor) Implements System.Web.UI.IScriptControl.GetScriptDescriptors
Return New ScriptDescriptor() {}
End Function
Public Function GetScriptReferences() As System.Collections.Generic.IEnumerable(Of System.Web.UI.ScriptReference) Implements System.Web.UI.IScriptControl.GetScriptReferences
Return New ScriptReference() {_scriptReference}
End Function
End Class
I hope the question makes sense. Thanks for taking the time to read through.
Ali
Answered this myself, I was getting confused with the assemblies and the constructors for ScriptReference. I just wanted a ScriptReference with the (mapped) name so I used the blank constructor and then set Name. I could then remove the assembly information.
Adjusting the following sorted the problem out:
Public Sub New()
' Add the resource mapping
ScriptManager.ScriptResourceMapping.AddDefinition("MyControlScript", New ScriptResourceDefinition With {
.Path = "Path.To.MyControlScript.minimised.js",
.DebugPath = "Path.To.MyControlScript.original.js"
})
' Set the script reference
_scriptReference = New ScriptReference() With {.Name="MyControlScript"}
End Sub

Instantiating a class within WCF

I'm writing a WCF WebMethod to upload files to, of which I taken snippets from around the web. The WCF interface looks like this:
<ServiceContract()>
Public Interface ITransferService
<OperationContract()>
Sub UploadFile(ByVal request As RemoteFileInfo)
End Interface
<MessageContract()>
Public Class RemoteFileInfo
Implements IDisposable
<MessageHeader(MustUnderstand:=True)>
Public FileName As String
<MessageHeader(MustUnderstand:=True)>
Public Length As Long
<MessageBodyMember(Order:=1)>
Public FileByteStream As System.IO.Stream
Public Sub Dispose() Implements IDisposable.Dispose
If FileByteStream IsNot Nothing Then
FileByteStream.Close()
FileByteStream = Nothing
End If
End Sub
End Class
Within ASP.NET, when the web method is consumed, for some reason it only works when the interface is used as part of the instantiation of RemoteFileInfo:
Protected Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
If fu.HasFile Then
Dim fi As New System.IO.FileInfo(fu.PostedFile.FileName)
' this is the line in question --------------
Dim cu As ServiceReference1.ITransferService = New ServiceReference1.TransferServiceClient()
' -------------------------------------------
Dim uri As New ServiceReference1.RemoteFileInfo()
Using stream As New System.IO.FileStream(fu.PostedFile.FileName, IO.FileMode.Open, IO.FileAccess.Read)
uri.FileName = fu.FileName
uri.Length = fi.Length
uri.FileByteStream = stream
cu.UploadFile(uri)
End Using
End If
End Sub
Can anyone advise why it is not possible to create an instance of TransferService using the following approach:
Dim cu As New ServiceReference1.TransferServiceClient()
If I try the above, it breaks this line:
cu.UploadFile(uri)
...and UploadFile must be called with three parameters (FileName, Length, FileByteStream) even there is no method that uses this signature.
Why is the Interface required when creating an instance of this class please?
When you create the proxy for your service with the "Add Service Reference" dialog, by default the proxy creation code will "unwrap" message contracts, like the one you have. If you want the message contract to appear as you defined on the server side on your proxy, you need to select the "Advanced" tab, and check the "Always generate message contracts" option. With that you'll get the message contract in your client as well.
The issue is that when a MessageContract is encountered as a parameter, the WCF client generation assumes by default that you want to implement a messaging-style interface, and provides the discrete properties from the message contract as part of the client-side interface.
The Using Messaging Contracts article in MSDN contains a very detailed description of what can be done with a messaging contract and I suspect that Microsoft chose this default behavior because of some of the "games" that you can play with the messages.
However, if you examine the code generated for your UploadFile on the client side, there are some interesting tidbits that help to explain what is going on.
The first is the comments for the UploadFile method in the interface:
'CODEGEN: Generating message contract since the operation UploadFile is neither RPC nor document wrapped.
...
Function UploadFile(ByVal request As ServiceReference1.RemoteFileInfo) As ServiceReference1.UploadFileResponse
This implies that the contract would have been generated differently if the message contract had a different implementation.
The second is that you will see that there is nothing special about the code that is used to actually make the service call:
Public Sub UploadFile(ByVal FileName As String, ByVal Length As Long, ByVal FileByteStream As System.IO.Stream)
Dim inValue As ServiceReference1.RemoteFileInfo = New ServiceReference1.RemoteFileInfo()
inValue.FileName = FileName
inValue.Length = Length
inValue.FileByteStream = FileByteStream
Dim retVal As ServiceReference1.UploadFileResponse = CType(Me,ServiceReference1.ITransferService).UploadFile(inValue)
End Sub
So in this case, your code is doing exactly what the generated code does. However, if the MessageContract were more complex, I suspect that this would no longer be the case.
So, for your question:
Can anyone advise why it is not possible to create an instance of
TransferService using the following approach...
There is no reason not to take this approach as long as you verify that the implementation of the method call is functionality equivalent to your code.
There are a couple of options for changing the default generation of the method in the client:
1) Remove the MessageContract attribute from the RemoteFileInfo class.
2) Although it seems to be counter-intuitive, you can check the Always generate message contracts checkbox in the Configure Service Reference Dialog Box.

Resources