Using the Sage 300 .Net API from ASP.Net MVC

6 minute read time.

Introduction

In this blog posting we are going to switch from using WinForms projects to an ASP.Net MVC project. ASP.Net MVC is Microsoft’s newest Web Development Platform. Be careful not to confuse ASP.Net MVC with ASP.Net. Both are still available and have similar version numbers, both are still part of Visual Studio, but they are quite different. The main problem with ASP.Net is that it doesn’t handle HTML5 web pages with lots of JavaScript well. Generally if you write a lot of JavaScript, the ASP.Net framework becomes pretty much useless. Microsoft then answered these complaints with ASP.Net MVC which is a more modern framework designed to build modern interactive web sites.

I’ve now installed Visual Studio 2013, so all the projects going forwards are going to be stored in that format. As a result I created the sample application that goes with this article in Visual Studio 2013 using ASP.Net MVC version 5.

MVC versus WinForms

I’ve been using WinForms for the samples in this series of articles on the Sage 300 .Net API because WinForms makes it really easy to write simple programs. I just create a simple project, throw some controls on the form, double click on the control and write some code to do something. Very simple and easy. But for the end result I just get a Windows application that needs to be installed on a given computer along with the .Net framework. ASP.Net MVC is for writing Web applications and it is much more complicated to get started. But the end result is a scalable web application that can be running on a farm of web servers and the UI runs in any browser on the clients computer with nothing else installed except the browser. I can produce UIs just as rich as with WinForms, but now they need to be specified in HTML5/CSS and there are a number of additional capabilities that they get as a result. With WinForms I can create global variables (or leave objects instantiated for the duration of the program), and keep state easily and pass data around freely. With ASP.Net MVC each operation causes new objects to be created and nothing is remembered from call to call (unless I do something special). This way a farm of application servers could be handling the requests each working independently. With WinForms there is no particular structure to the programs I produced, In ASP.Net MVC we are dealing with a very definite MVC structure.

MVC

Model – View – Controller (MVC) is a design pattern for creating more robust and more maintainable user interfaces programs. It separates the concerns into three parts to produce a more modular design.

I’m not going to go too much into the details of creating a program and setting these up, since there are dozens of really good tutorials on the Internet like this one. Rather let’s look at our example and talk about the various elements in a real setting.

Sample Program

For a sample program I ported the first WinForms application to ASP.Net MVC. This one is the ARInvEntry project. It basically puts up a web form where you enter the customer number and then hit the “Create Invoice” button and it creates an A/R Invoice for that customer. The main goal here is to get a starting project with a Razor View, a controller and then a Model that calls into the Sage 300 Business Logic using our .Net API.

Note that since Sage 300 ERP is a 32 Bit application, you must run this project as a 32 Bit application, which means if you run this through IIS, you must have the application pool used set to have 32 Bit mode enabled (probably the default application pool).

In this program the main web page is a razor view and it is connected to the model which allows the framework to provide data binding of the customer number into the model, so we don’t need to write any code to move the data from the browser into the model’s member variable. Inside Index.cshtml there is the statement:

@model ARInvEntry.Models.CreateInvoice

 

Which connects the View to the Model. Then the form is defined by:

        @using (Html.BeginForm("CreateInvoice", "Home")) {

        <p>

            Customer Number:

            @Html.TextBoxFor(model => model.CustomerNumber)

        </p>

        <p>           

            <input type="Submit" value="Create Invoice" />

        </p>

Notice that this code is a combination of HTML like <p> as well as the template helper functions like @Html.TextBoxFor (whose argument binds it to the model’s member variable). The Html.BeginForm command connects the “Create Invoice” button to the controller’s action method. “Home” is the name of the controller (which was generated by Visual Studio) and its code is in HomeController.cs. Then the first argument “CreateInvoice” is the method to call when the form is submitted (ie the button is pressed). All the @ tag template functions will be converted to pure HTML by the razor view engine when the page needs to be generated.

It may not look like there is a lot of glue holding things together here, that is because ASP.Net does a lot of things by convention, and so if you don’t specify something explicitly, it has a convention to find it. So generally if things have the same (or similar) names then they go together. This makes coding faster since you just follow some coding conventions and then all the attendant glue is provided automatically and you don’t need to worry about it. This convention over coding approach takes a bit of getting used to, but once you are, it makes development go quite a bit quicker.

In the controller (HomeController.cs) there is the action method which gets called when the user hits submit:

        public ActionResult CreateInvoice(Models.CreateInvoice crInvObj)

        {

            crInvObj.DoCreateInvoice();

            return RedirectToAction("Index");          

        }

Basically this is called with the model as a parameter where the data bound members will already be filled in. So all it has to do is call the method in the model to create the invoice.

It then returns redirecting us back to the main page.

The model has a public member CustomerNumber:

        public string CustomerNumber { get; set; }

 

which is used by the data binding support and populated automatically from the browser. Then there is the DoCreateInvoice method that contains the code from the previous project to create the invoice.

Limitations and Future Work

At this point, this is a very basic MVC project which just really establishes our framework for future work. There is no error reporting (except for writing to the VS output window). After you hit submit, we do the work and then return a complete page. We aren’t doing the searching we supported in the WinForms application.

For the error reporting we can’t just popup a message box from the Model when an error occurs. Generally all UI communications needs to be communicated from the model back to a View. We could add JavaScript to the View to get the response from the model to display a message box (JavaScript alert). We could add a new razor view for displaying error and status messages. We could provide a message area on the main form to fill in. We’ll look at implementing some of these in future articles.

Right now when the invoice is created, we simply refresh the home screen. This isn’t particularly efficient or elegant. Partly this is because of how the submit button is implemented as a form submit. What we would really like to do is to submit an Ajax web service request when the button is pressed and then just update select parts of the screen based on the reply.

If you choose to deploy this project to Azure as a PaaS application, you will run into problems due to the dependency on the Sage 300 .Net API which requires at least workstation setup be installed so we will need to talk about how we deploy a project of this nature to the cloud.

Summary

This article presents a very simple ASP.Net MVC application who’s Model communicates with Sage 300 via our .Net API. Now that we have this starting point, we can start developing some new elements to the project and explore various aspects of writing programs with ASP.Net MVC.