Writing to an output text file and finding out extra characters or lines in it?

If you’re using File.OpenWrite() to create the output file, make sure the output file does not exist.  This MSDN article explains what happens if output file exists:

For an existing file, it does not append the new text to the existing text. Instead, it overwrites the existing characters with the new characters. If you overwrite a longer string (such as “This is a test of the OpenWrite method”) with a shorter string (such as “Second run”), the file will contain a mix of the strings (“Second runtest of the OpenWrite method”).

Advertisements

How Many Ways Can You Add Entity Framework Model To Your Project?

Let me count the ways.  3?  Well there are at least 3 ways you can add Entity Framework (EF) model to your .NET project, that I know of.  One is Code First, second is Reverse Engineer Code First, and third is the ADO.NET Entity Data Model (EDMX).

Code First, as the name suggests, requires you to code your EF model.  Yep, this requires more coding but gives you  a lot more control.  Usually you go this route if you don’t have an existing database to model or you want to create a fresh new database for your project.  I have not tried this approach as mostly the projects I worked on already has existing database. 

In Code First, basically you create the classes that model your database,  optionally configure your classes using Data Annotations (via class / property attributes) and/or Fluent API, and then create the database based on that model.  When you update the model, you can use Code First Migrations to update the database.  Microsoft’s Code First to a New Database has a video and a step-by-step walkthrough on how to go about this approach.

Reverse Engineer Code First uses EF Power Tools to generate the code for you containing the DbContext class, POCO classes, and Code First mapping classes, based on an existing database.  EF Power Tools Summary of Commands shows you a step-by-step walkthrough on how to do this plus some more, including customizing the default reverse engineer T4 templates and generating pre-compiled views to improve start-up performance. 

If you need to edit the t4 templates, I suggest getting a t4 editor such as tangible T4 Editor from the Visual Studio Gallery so you can get syntax highlighting at least.  When it comes to tweaking performance, Performance Considerations for Entity Framework 4, 5, and 6 has some tips.  One way is to generate pre-compiled views.  Pre-Generated Mapping Views shows you how to do this using EF Power Tools and also via APIs provided in EF6 onwards.  How to: Pre-Generate Views to Improve Query Performance shows you how to generate pre-compiled views using EDM generator command line tool.

Code First and Reverse Engineer Code First does not automatically generate an ADO.NET Entity Data Model (EDMX) file.  Same goes too for EDMX, it does not automatically generate any code.  To generate the code you get from Code First in EDMX, you need to add a code generation item, basically download a t4 template and generate the code based on it.  Database First shows you how to create an EDMX from an existing database, view and edit it in EF Designer and generate the code.  How to: Create a New .edmx File (Entity Data Model Tools) has a section on adding EDMX from an existing database and contains tons of links to more information, definitely a good resource.

It can get confusing what these code first and database first mean.  It all lies down to how you synchronize your model changes between the database and code or more accurately where you make your model changes, is it in code or database?  Although in reverse engineer code first, you can change your model in the database, and re-generate the code, essentially doing a database first.

Ways Developer Can Secure An ASP.NET Application, Part 1

Calling .Net Assembly from VBA

Stuck in VBA?  You don’t have to be.  You can move all your business logic code from VBA to a .Net assembly.  It’s easier than you might think and this post will show you how.

First you need to create a new Class Library project and below is the basic structure of a COM-callable wrapper for your .Net assembly.

// need this so we can decorate our classes with ClassInterface
//  and ComVisible attributes
using System.Runtime.InteropServices;

// namespace should be the same as assembly name
//  so when VBA calls it via New or CreateObject() it will use same reference name
//   and prog ID
//   ie. New YourNetAssembly.TestFunc or CreateObject("YourNetAssembly.TestFunc")
namespace YourNetAssembly
{
    // need to decorate class with following attributes
    //  so we can access its members using intellisense in VBA editor
    [ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class TestFunc
    {
        public int Add(int num1, int num2)
        {
            return num1 + num2;
        }
    }
}

 

And when you are ready to compile or build, the next thing you need to do is check the Make assembly COM-Visible in your project’s Properties –> Application –> Assembly Information….

Now if you are developing your VBA application (be it MS Access or MS Excel) locally or on the same computer where you build your .Net assembly, you can have Visual Studio register your COM automatically by checking the Register for COM interop in your project’s Properties –> Build.

But if you are developing your VBA application remotely or on a different computer, then you will need to copy your .Net assembly to that computer and manually register it using regasm.exe.  You might want to create a batch file containing the following command so you don’t have to type it every time.

c:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe YourNetAssembly.dll /codebase /tlb

Note the correct .Net Framework version that your .Net assembly is created in.  Each version of the .Net Framework will have its own folder.  Also this command is run from the VBA application folder where the .Net assembly resides.  Yours might have a different setup so take note.

/codebase option adds the .Net assembly’s path on the disk to the Windows registry.  /tlb option generates the type library and saves it on the same folder as your .Net assembly.

Note that you need administrator privileges on the computer to generate a type library, be it via Visual Studio or regasm.exe.  If you already have an administrator privilege, you need to open Visual Studio or the command prompt as admin by right-clicking and selecting Run as administrator.

Once registered, you then add a reference to it from your VBA application.  From the VBA editor, go to Tools –> References… and look for your .Net assembly in the list of Available References.  Its name should be the assembly name.  You can check the assembly name in your project’s Properties –> Application under Assembly name.  Once added, you can now start calling your .Net assembly from VBA.

There are two ways you might want to call your .Net assembly.  Using the New keyword, or using CreateObject().

Dim objTestFunc As New YourNetAssembly.TestFunc
' OR ...
Dim objTestFunc As Object
Set objTestFunc = CreateObject("YourNetAssembly.TestFunc")

Dim intResult As Integer
intResult = objTestFunc.Add(1, 2)
MsgBox intResult

 

Great, but how about debugging or stepping into the .Net assembly?  Well if you have both Visual Studio and VBA development environments on one machine, then it would be easier.  You just set a breakpoint inside your .Net assembly in Visual Studio.  Then in your project’s Properties –> Debug, enter the full pathname to the program that runs your VBA application (maybe MS Access or MS Excel) in Start external program.  Then in the Command line arguments, enter the full pathname to your VBA application.  Save changes then press F5 to run.  This will run MS Access or MS Excel (whichever one you are using) which in turn runs your VBA application.  When your VBA application calls your .Net assembly, it will break into the Visual Studio debugging environment.

What about if your VBA development environment is on a different machine?  Well hope is not lost yet.  Assuming you have a debugger program installed on that machine, you can place a Debug.Assert(false); or Debugger.Break(); in your .Net assembly and this will force it to go into debugging mode when it hits that code and open the debugger program.  Be sure to copy the PDB (debug) file for your .Net assembly plus the source code so you can step through .Net code.

        public int Add(int num1, int num2)
        {
            System.Diagnostics.Debugger.Break();
            // OR ...
            System.Diagnostics.Debug.Assert(false);

            // if Debugger.Break() does not work properly i.e. it does not return back
            //  to the VBA application after debugging, 
            //  then use Debug.Assert(false) instead

            return num1 + num2;
        }

 

So that’s all there is to it.  Easy eh?  So start coding away then!

EDIT:

Actually you don’t need to check the Make assembly COM-Visible in your project’s Properties –> Application –> Assembly Information…. unless you want to expose all your public classes in the assembly.  And besides since you still need to decorate your public classes with COM attributes, might as well just use COM attributes to select only those ones you want to be COM-visible.

I found this great article that summarizes what you need to do: Best Practice in Writing a COM-Visible Assembly (C#).  I didn’t bother adding the ProgId attribute to my COM-visible classes though, but the rest I did.  Plus I created an interface for each, as was suggested in the article.  Nice thing having an interface is you can control which methods in your COM-visible classes you want to expose, giving you a more granular level of control.

ASP.NET Web Services – Blast From The Past (Part 2)

Here is part 2 of this topic as promised.  It will cover consuming web service using HTTP POST and using jQuery AJAX.  If you missed part 1 of this topic, click here.

But before I start, I forgot to mention in part 1 that when you set up your web service as part of a web site, like when you deploy your web service in a virtual directory of a web site, you need to make sure the <compilation> setting in the web site’s web.config file does not have the targetFramework attribute which is usually present when targeting .NET Framework 4.0 and up.  Otherwise, your web service will not work.  Ok, so on to part 2.

 

Consuming a Web Service Using HTTP POST

Another article that covers the basics of a web service including consuming it using HTTP POST is Understanding the Basics of Web Service in ASP.NET.  I have a demo web page that uses HTTP POST to consume the simple web service I created.

Some important points:

  • When you use this method, you need to add the below config to the web service’s web.config file, otherwise you will get this error.
<configuration>
    <system.web>
		<!-- enable HttpGet and HttpPost on the web service -->
		<webservices>
			<protocols>
				<add name="HttpGet" />
				<add name="HttpPost" />
			</protocols>
		</webservices>
    </system.web>
</configuration>

 

  • The response you get will be displayed in the browser in XML format (see my demo web page).  If you want to handle the response, you need to code to send a POST request and handle the response, as in below:
protected void Translatev2Button_Click(object sender, EventArgs e)
{
	if (EnglishTextBox.Text != string.Empty)
	{
		try
		
{
	// this is the content of the request
	byte[] content = System.Text.Encoding.ASCII.GetBytes(
		"english=" + EnglishTextBox.Text);

	// create the request
	System.Net.WebRequest request = System.Net.HttpWebRequest.Create(
		"http://rodansotto.com/asmx/" +
		"TranslateToFrenchService.asmx/TranslateToFrench");
	request.Method = "POST";
	request.ContentType = "application/x-www-form-urlencoded";
	request.ContentLength = content.Length;

	// write the content to the request stream
	System.IO.Stream requestStream = request.GetRequestStream();
	requestStream.Write(content, 0, content.Length);
	requestStream.Flush(); 

	// get the response
	System.Net.WebResponse response = request.GetResponse();
	// get the stream associated with the response
	System.IO.Stream responseStream = response.GetResponseStream();
	// pipes the stream to a higher level stream reader with the 
	//  required encoding format
	System.IO.StreamReader streamReader = 
		new System.IO.StreamReader(
			responseStream, System.Text.Encoding.UTF8);

	// the response is in XML format and normally needs to be handled
	// but since the XML response is simple enough that when displayed
	//  by the browser, it only displays what we need to display,
	//  the french text
	FrenchLabel.Text = streamReader.ReadToEnd();
}
		
		catch (Exception)
		{
			throw;
		}
	}
}

 

Consuming a Web Service Using jQuery AJAX

Another way to call a web service is by using jQuery.ajax() function.  This is the preferred way by many.  Understand jQuery Ajax Function: Call Web Service Using jQuery Ajax Method shows you how.  Below is the client-side code for my demo web page that uses jQuery AJAX to consume the simple web service I created.

<head runat="server">
    
    <script src="http://ajax.googleapis.com/.../1.11.2/jquery.min.js">
    </script>
    <script>
        $(document).ready(function () {
            $("#TranslateButton").click(function () {
			
// have to add following statement to enable cross-domain request
$.support.cors = true;

$.ajax({
	type: "POST",

	url: "http://rodansotto.com/...Service.asmx/TranslateToFrench",

	//contentType: "application/x-www-form-urlencoded; charset=UTF-8",
	// no need to specify contentType above as that is the default

	data: "english=" + $("#EnglishTextBox").val(),

	dataType: "text",

	success: function (response) {
		$("#FrenchLabel").html(response);
	},

	error: function (jqXHR, textStatus, errorThrown) {
		var errorMsg = "jQuery AJAX ERROR!!!\njqXHR.statusText = " + 
			jqXHR.statusText + "\ntextStatus = " + 
			textStatus + "\nerrorThrown = " + errorThrown;
		alert(errorMsg);
	}
});
				
            });
        });
    </script>

 

Some important points:

  • If your web app will be making a cross-domain request to call the web service, you need to set $.support.cors = true, otherwise you will receive the ‘No Transport’ error.
  • And don’t forget to enable the following attribute in your web service class: [System.Web.Script.Services.ScriptService].
namespace MyWebService
{
    /// <summary>
    /// Summary description for TranslateToFrenchService
    /// </summary>
    [WebService(Namespace = "http://rodansotto.com/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script,
    //  using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class TranslateToFrenchService : 
        System.Web.Services.WebService
    {

 

And that concludes this topic ASP.NET Web Services – Blast From The Past.