Thursday, January 14, 2016

No More Postbacks! From MVC to WebForms.

I really love MVC. A lot. However, my current job heavily depends on ASP.NET WebForms and a complete conversion to MVC is just not feasible.

I've developed some techniques while working in this environment that have helped me tremendously, and I haven't seen them used anywhere else.
So I will share this one with anyone who is interested.

In particular, I'm mimicking controller actions from MVC in WebForms.

It's perfect for client-side JavaScript development and I use it to essentially drive all of the Kendo UI stuff I've implemented at work.

So I'll make this short and sweet.

I need to pass JSON to the client, but how do I do that without setting "hidden fields" in the code-behind and other silly WebForms magic?

This post explains how I've achieved this in the most natural way possible.

This technique can be used in any ASP.NET WebForms project that needs to be dynamic without using "postbacks" or "UpdatePanels."

We will use Ajax to request the same page we're on asynchronously, but with a query string to specify which action we want to execute.

/Foo.aspx
function ajax(action, type, dataType, data, callback) {  
 $.ajax({
  url: '/Foo.aspx?action=' + action,
  type: type,
  dataType: dataType,
  data: data,
  success: function(data) {
   if (callback && typeof(callback) === typeof(Function)) {
    callback(data);
   }
  }
 });
}

function print(data) {
 console.log(data);
}

ajax('GET_SomeJson', 'get', 'json', {}, print);

Behind the scenes, we get the "action" query string from the Request object, and route it through a Route method.

/Foo.aspx.cs
protected void Page_Load(object sender, EventArgs e) {
 if (!this.IsPostBack) {
  var action = Request.QueryString["action"];

  if (!string.IsNullOrEmpty(action)) {
   Route(action);
  }
 }
}

protected void Route(string action) {
 var json = string.Empty;

 switch (action.ToLower()) {
  case "get_somejson":
   json = new JavaScriptSerializer.Serialize(new Bar());
   break;
 }

 if (!string.IsNullOrEmpty(json)) {
  Response.Write(json);
  Response.End();
 }
}

// example class to serialize as json
public class Bar {
 public string Message { get; set; } = "Hello, World!";
}

When I need to pass parameters to one of my actions, I pass them in an object via $.ajax(), and I receive them through Request.Params on the server-side.

Here's an example (I'm recycling the ajax() function I wrote earlier):

/Foo.aspx
ajax('POST_ActionWithParams', 'post', 'text', { someParameter: 'some value' }, print);

I tap into Request.Params to build a dictionary and modify my Route function so that it can accept parameters.

/Foo.aspx.cs
protected void Page_Load(object sender, EventArgs e) {
 if (!this.IsPostBack) {
  var action = Request.QueryString["action"];
  var parameters = new Dictionary<string, string>();

  foreach (var key in Request.Params.AllKeys) {
   parameters.Add(key, Request.Params[key]);
  }

  if (!string.IsNullOrEmpty(action)) {
   Route(action, parameters);
  }
 }
}

protected void Route(string action, Dictionary<string, string> parameters) {
 var json = string.Empty;

 switch (action.ToLower()) {
  case "get_somejson":
   json = new JavaScriptSerializer.Serialize(new Bar());
   break;

  case "post_actionwithparams":
   json = ActionWithParams(parameters);
   break;
 }

 if (!string.IsNullOrEmpty(json)) {
  Response.Write(json);
  Response.End();
 }
}

private string ActionWithParams(Dictionary<string, string> values) {
 var value = string.Empty;

 foreach (var key in values.Keys) {
  switch (key.ToLower()) {
   case "someparameter":
    value = values[key];
    break;
  }
 }

 return value;
}

Now all I'm missing are models and views. :P

I figured this was a pretty neat trick and that other people might find it useful.

For the record, I don't mind working in WebForms, but I will always prefer MVC.

Thursday, August 20, 2015

Latest Developments

A lot of people mentioned to me that I sort of stopped updating my blog.

That's true, but here I am!

I enjoyed BMSi a lot. I learned a lot about the medical industry: terminology, procedures, codes, etc. 

Near the beginning I was working on a multi-threaded, socket-driven medical software suite of applications built in .NET. I had very little VB.NET experience, other than the class I took in college. But my many years of C#.NET transferred well into the VB.NET world. I was a rockstar with 0 years of professional experience.

But too much VB is bad for the soul. There are a lot of things that I just don't like about VB. C# is automatically strict, the code is smaller, more elegant, case-sensitive, and pleasing to my brain. VB also introduced me to the concept of global modules (basically public classes with static members, but totally different). That breaks object-oriented design.

Enough of the anti-VB talk. Google has plenty of other links to online vented VB-hatred.

About halfway through my career at BMSi, the chief software developer left to be CIO of some other company. I inherited his web projects and instantly fell in love with web development. So I spent several months maintaining and developing his ASP.NET projects and WCF SOAP services. And the past seven months of my career I developed an ASP.NET MVC 5 application for my grand finale.

It essentially consisted of seven pieces of software (excluding the SQL Server database):

A studio to map Word document pages to PowerPoint slides, edit mappings/slides, etc. 
A presentation platform to present the mapped presentations to attendees at various seminars.
A website for users to see both the slides and the pages (AJAX-loaded when a new association was found in a new slide).
A web server for sending the slide information from the presentation platform to the website.
A synchronization tool for synchronizing intranet served data to and from the internet-based website.
A document converter for converting the Word document into PDFs (so I could display them with PDF.js).
A conversion library for defining the conversions (PPT->Image, PDF->Image, DOC->PDF, DOC->DOCX) and mapped presentation data structure.

I spent about seven months before I completed the entire thing and had tested it at the seminars a few times. So I averaged a huge project per month; which is not too shabby for a guy with less than two years of professional experience.

I learned how I work under pressure. My constraints, strengths, and weaknesses. I learned a bit about myself throughout the entire ordeal. I also got deeply entrenched in the world of web development thanks to this.

I'm now working at ImageNet Consulting in downtown OKC as a software developer. But I only work with ASP.NET and SQL. And guess what? I'm using C# again! I absolutely love my new job. I've already produced production quality code in my first couple of weeks and am coming along fairly well.

I've never really worked at a rigid Agile shop before. BMSi was very erratic in terms of its project management methodology. I'm not even sure if they really had one. I was getting requests for new features on average every thirty minutes to an hour. Some days I'd go an entire day without any feature requests. Poor planning and not really knowing what we wanted left us with stacks of scope creep. They broke Brook's law by bringing in the other junior (who's very talented by the way) far too late into the project. Basically the last week I was there, I was given the task of bringing him up to speed. On my thousands of lines of code over several different projects. Ha. I have faith in that guy though. Hopefully he finds what he's looking for.

Anyway, back to ImageNet. It's real, authentic Agile. I get weekly sprints (as opposed to hourly), and am surrounded by other experienced developers if I need a little help. Because remember, I'm still technically junior. I feel intermediate, but when I jump into a foreign code-base and database, it will take some time for me to ramp up.

I'm having fun, and learning a lot. And doing exactly what I've always wanted to do. I'm working downtown, writing software, and sleeping well at night. I'm finally content.

These 4278 characters should hold you people off for awhile. :P

Saturday, April 12, 2014

SMS to Machine

So today I wrote an Android app that lets you text from your computer (so long as it has a JRE).

Basically the server (SMS to Machine) runs on your phone in the background and you can connect to it from the desktop client (SMS Client) using the address provided by the server. All of the messages are encrypted with a password in the form of a SecureSMS object (essentially a pretty container with an array list of encrypted strings).

I wrote a miniature messaging protocol for the communication. All SecureSMS messages are wrapped with [BEGIN] and [END] tags to let the server/client know where content begins and were it ends. The connection first has to be accepted when the [CONNECT] command is sent. A disconnect can be achieved when the [DISCONNECT] command is sent. All other transmissions right now only contain encrypted content to be decrypted by either end of the connection.

Currently I'm still in a testing stage. It sends and receives fine, but I still have work to do. I've decided I'm going to send metadata in the form of JSON using the framework provided at json.org. And I plan on handling MMS by zipping images and sending a "SecureMMS" object through the output stream.

This sort of application already exists in the Playstore, but I honestly don't care. I'm doing this for fun (as with everything I write).

As of right now, it's a very small but powerful application with a primary focus on minimalism. I'm all about minimalism. And as few bugs as possible. ;P

Okay. Back to coding!

Thursday, April 10, 2014

The Battle for Optimization

So a little update on ZerothScript. The project has come along smoothly. But for the first time in years, I've come across an optimization issue. I set up my unit test in the form of scripts. One script for USL and one script for ZS. The test creates a variable for storing numerical values and loops one hundred thousand times decrementing the value by one each iteration. At first ZS was clocking in a little over half a minute while USL was finishing at nine seconds. This seriously boggled my mind. I didn't think something I wrote three years ago could possibly be any more efficient than what I can write now. I couldn't be more incorrect. I attacked this slowness issue in two ways: rewriting the interpreter, and removing the logger calls. Starting with the interpreter, I was passing the tokens down the chain of command and it was grossly inefficient. The interpreter is much more organized thanks to the analyzer function I wrote. The interpreter no longer needs to pass off the tokens down the chain of command. It goes directly to where it's supposed to go. This increased the speed by a lot but it wasn't good enough. The real speed increase came from removing the calls to the logger. Previously each call printed to stdout the stack trace. That was a terrible idea. I have no idea why I thought that would be a good idea. So this functionality has been destroyed. The error logging will still exist because it's necessary. I forgot the nature of a language of this sort required the code to be as bare bones as possible.

I was able to cut the time down to fourteen seconds. Those are incredible results to me. It's only five seconds slower than USL now. I'm about to merge the shell into the interpreter for efficiency purposes. Right now the only function of the shell is to contain variables and methods. It doesn't do anything else. So merging seems completely appropriate. I'll only merge the appropriate functions and variables. I can abide by the Law of Demeter in this case since calls to the shell just to get their variables (and their values) are heavily used throughout the interpreter. It was a good idea at first, and maybe it still is, but as of right now, optimization is what I need. I need this language to be faster and more powerful than USL. I truly believe that I can achieve the same speed if not better. It will take time, but I will get there. And if I optimize sooner than later, I won't have to work through a finished project to optimize everything.

I'm learning more and more as a software developer each day. Professionally, and on my own time. I'm seriously blessed to have this skill. I wish I knew more people who were as passionate about code as I am. One day, when (and if) I leave Oklahoma, maybe that will happen.

Okay, so what's new in ZS since I left off?

I've implemented variables (of type integer, double, and string) and for loops. I actually got nested for loops down to one nest! I had to deprecate nested control structures in USL. It doesn't seem like a lot of functionality right now (at least to me), but later on down the line (next month or so), I will have a completed language to expand upon. Right now I'm going to continue working on optimizations and start implementing if-statements. Then I will implement methods.

So this post is about an issue I had encountered, and how I handled it. I had to drop unnecessary features and rewrite some things, but in the end it was worth it.

Until next time! I'll probably check in the changes right now just for the heck of it.

Here it is: ZerothScript

Saturday, March 29, 2014

ZerothScript

I've been writing a new scripting language for the past week and I call it "ZerothScript" or "ZS".

ZerothScript ("ZS") is a hybrid typed, object-oriented scripting language. By hybrid typed, I mean, it will allow the retyping of a variable after initialization. The type checking of USL is absent in ZS. Variable types will be declared statically; however, the types can be dropped and replaced with other types. When the type changes, the value changes accordingly.

ZS will feature a programmable interactive shell, just like USL, except the concept of the shell has been abstracted and divided into three main components: the engine, the interpreter, and the parser. The engine can be best understood as just a means to receive input from the user (or via script). The parser is the first to touch the input, and depending on whether it's something the parser handles (creating a new shell, exiting the shell), it will pass the appropriate values back to the engine. If the engine gets a request for a new shell, it will add a shell and attach that shell to the interpreter. The shell is a stateful creature and an interesting data structure (in my opinion) because it is basically a giant container of information (starting off small of course). If the engine gets an unhandled response, it passes it off to the interpreter for interpretation. The interpreter is attached to the current shell in the engine, so anything that happens in there will be reflected in that particular shell.

This is the core of ZS. The rest will come in time as I continue its development.

ZS already has a skeleton for a cool error handling system and a cool debug mode logging utility. When I have some cool ideas, I'll jot them down in code. Here's an example of what I expect the finished product to look like:

# begin example script

class Object
    private
        _id as String
    public
        def new(id as String)
            self._id = id
        end
        def getID() as String
            return self._id
        end
        static def sayHello()
            say "Hello, World!"
        end
end

Object.sayHello()

o = Object.new("object")
say "I am an object of type #{Object.class} and I have an ID of #{o.getID()}"

# end of script


Similar to USL, eh?

You can view my progress at GitHub.

Monday, January 20, 2014

My First Programming Job

I can now call myself a professional. This is seriously my dream come true.

I won't let them down. I am going to work as hard as possible. I bought Murach's book, Visual Basic 2012, last week and I'm already at page 630.

My life is finally falling into place.

And I could never be thankful enough. :]

Wednesday, January 8, 2014

SysMon update

I've been programming exclusively in VB .NET for the past few days now, and I'm pretty much happy with this language overall. I am still able to do the same things I used to thanks to .NET, and it's starting to grow on me.

Today I decided to work on SysMon again. I added a TabControl (.NET version of javax.swing.JTabbedPane), and a ContextMenu (.NET version of javax.swing.JPopupMenu) to control the components within the tabs. I added a Services tab which lists all Windows services, and when you right-click the list, it selects the index and shows the context menu (allowing you to toggle a service on or off). In that toggle, I learned how to use the VB version of the ternary operator. It's an If-statement used as an initializer! Very insane! I also changed the color scheme back to a more orthodox Windows style.

Screenshot time!


It's up at github!