Posts Tagged ‘Web Programming’
Combining WebServices with MVC
I always liked the concept behind WebServices. Having a single place to store a bunch of complex but commonly used functions is a great way to decrease complexity of other programs that all sit on the same network. If you’re like me and tend to do a lot of intranet applications, a web service can prevent a lot of duplicate code.
My only real problem with WebServices was having to use SOAP. Adding a Web Reference to a project wasn’t that big of a deal but if you ever wanted to just call a function real quick, say from a script file (yes, I do VBScript occasionally… ick) then it isn’t quite as I’d prefer. You end up spending more time making sure your XML is well formed and less time on the logic inside your quick script.
MVC helps get around that problem by allowing you to perform normal HTTP calls and plug all your arguments into the query string or the body of the request – something much easier to do. The problem, however, is that you end up losing the convenience of using a WebService with other applications.
A Simple Solution
The idea here is to create a controller that acts as a wrapper to a WebService. By doing this we can override a few methods on our Controller that use reflection to invoke the matching method on the WebService. Also, because the Controller is still a unique class, we can still attach any number of Actions to it as we normally would. Below is some code that I wrote the other day. It isn’t battle tested so if you use it be sure to verify it does everything that you need it to do.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Mvc;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.IO;
namespace Interface.Controllers {
/// <summary>
/// Abstract wrapper that handles calling WebService methods on behalf of a controller
/// </summary
public abstract class WebServiceControllerWrapper<T> : Controller where T : WebService {
#region Constructors
/// <summary>
/// Creates a new Controller Wrapper for a WebService
/// </summary>
public WebServiceControllerWrapper() {
this.Service = Activator.CreateInstance<T>();
}
#endregion
#region Properties
//The service that is being used for this call
private T Service { get; set; }
#endregion
#region Overriding Methods
//finds the correct method for the WebService method
protected override void HandleUnknownAction(string actionName) {
//find if the method exists
MethodInfo method = this.Service
.GetType()
.GetMethods()
.Where(found =>
found.IsPublic &&
found.Name.Equals(actionName, StringComparison.OrdinalIgnoreCase) &&
found.GetCustomAttributes(typeof(WebMethodAttribute), true).Count() > 0
)
.FirstOrDefault();
//if no method was found, just give up
if (method == null) { return; }
//check if all the arguments were found
List<object> arguments = new List<object>();
ParameterInfo[] parameters = method.GetParameters();
foreach (ParameterInfo param in parameters) {
//check if this argument was found
object arg = this.ValueProvider[param.Name].ConvertTo(param.ParameterType);
arguments.Add(arg);
}
//with the arguments try and call the result
object result = method.Invoke(this.Service, arguments.ToArray());
//if there is a return value, serialize it and write it
this.Response.ContentType = "text/xml";
if (method.ReturnType != null) {
//if this is an XElement of some kind, just use it as is
if (result is XObject) {
//write the string
using (StreamWriter writer = new StreamWriter(this.Response.OutputStream)) {
writer.Write(result.ToString());
}
}
else {
//try and serialize it
XmlSerializer serialize = new XmlSerializer(result.GetType());
serialize.Serialize(this.Response.OutputStream, result);
}
}
}
#endregion
}
}
The idea here is to inherit this class instead of the standard Controller class and provide the name of the WebService we want to wrap around as our Generic argument. For example…
//that's about it - actions are mapped automatically to the correct method on the webservice
public class AccountController : WebServiceControllerWrapper<AccountWebService> { }
By doing this, when our controller receives an Action, is checks the WebService instance for the same method and then tries to call the method with the arguments it finds as part of the request!
And that’s it! A quick and simple way to map incoming actions to a matching method on a Web Service!
The Return Type
I’m not sure the best way to handle the return type at this time. It seems to me that the XmlSerializer should be sufficient for object with the exception of Xml which should probably just be written out as a string. If you have a suggestion on a better way to respond to incoming requests, please let me know.
Remember: This is just some quick and dirty code – This needs some more polish and exception handling before I’d use it in a real project, but at least it might help you get going in the right direction.
Using WebControls In ASP.NET MVC Views – Part 2
In this post we continue the investigation if we can put WebControls inline with a MVC ViewPage. If you read my previous post on this topic, you’ll remember we got close, but couldn’t quite get it to work as expected.
You might be thinking “you shouldn’t use WebControls in Views!!” and you are absolutely right! I have two reasons for doing this project.
- A lot of investment has been put into creating WebControls. Some developers may not want to switch to MVC because they don’t want to lose everything they have already put together. Having this option available might help move them in that direction.
- I wanted to see if it was even possible to do!
I don’t really recommend mixing the two worlds together that much, but this might be handy for someone at some point somewhere (somehow…)
This is a series of posts to investigate if it is possible to use WebControls inline with MVC. The code in this post is not a final version and shouldn’t be used. Additionally, at the time of writing this I already have the code done for part 3 so I know the code gets better, but I still need do part 2 before I move to part 3. Hang in there!
It’s Just HTML
One thing I’ve kept repeating to myself while working on this is ‘it’s just HTML’ — If you think about it, we only need to get rendered content and post it back to the server in the same way that a normal WebForms page would do it. However, the ASP.net page lifecycle is not just HTML, in fact, there is a lot that goes into it.
If you remember, in the last attempt we we’re able to hook up events to our WebControls and then render them inline with the rest of our MVC content. We then used the BuildManager class to load an instance of a page and then process the request — but only to be met with a strange error message about our ViewState.
While I never did entirely figure out what the specific problem was I did suspect it had something to do that the ViewPage was some how having a problem with the ViewState that we were posting back that was actually rendered by the dynamically loaded page. If it doesn’t make sense, don’t worry — I’m still guessing here.
In any case, it appears that we were still on the right track. After a little more hacking I came up with the following code.
//snip...
/// <summary>
/// Class to allow WebForm Controls to be used inline with MVC
/// </summary>
public static class WebFormExtensionMethods {
/// <summary>
/// Executes a delegate to generate the control to render onto the page
/// </summary>
public static void RenderWebFormControl(this ViewPage page, Func<Control> gen) {
WebFormExtensionMethods.RenderWebFormControl(page, gen());
}
/// <summary>
/// Renders a WebControl onto the page that supports postbacks
/// </summary>
public static void RenderWebFormControl(this ViewPage page, Control control) {
//the name of the loader container and the viewstate hack
string path = "~/ViewPageWithWebForm.aspx";
string mvcPrefix = "MVCSTATE";
//load the container and add the control
WebControlOutputPage template = (WebControlOutputPage)
BuildManager.CreateInstanceFromVirtualPath(path, typeof(WebControlOutputPage));
//add the control to the page
template.Init += (s, e) => {
template.Form.Controls.Add(control);
};
//capture the output to format
template.Rendered += (output) => {
//change the names of the viewstate items to prevent
//postback errors
XDocument doc = XDocument.Parse(output);
foreach (var item in doc.Descendants()
.Where(o => o.Attribute("name") is XAttribute &&
o.Attribute("name").Value.StartsWith("__"))) {
//change the state name
item.Attribute("name").Value = string.Concat(
mvcPrefix,
item.Attribute("name").Value
);
}
//display each of the elements inline
foreach (XElement show in doc.XPathSelectElement("html/body/form").Elements()) {
page.Response.Write(show.ToString());
}
};
//generate a query string of all the requested items
//there is probably a much better way to do this
StringBuilder query = new StringBuilder();
foreach (var item in page.Request.Params.AllKeys) {
string name = item.Replace(mvcPrefix, string.Empty);
query.Append(name + "=" + page.Server.UrlEncode(page.Request[item]));
if (!page.Request.Params.AllKeys.Last().Equals(item)) { query.Append("&"); }
}
//create a new HttpRequest to process the request with
HttpRequest req = new HttpRequest(
path,
page.Request.Url.AbsoluteUri,
query.ToString()
);
//process the container page
((IHttpHandler)template).ProcessRequest(
new HttpContext(req, new HttpResponse(new StringWriter()))
);
}
}
/// <summary>
/// Page rendering class for WebControl output
/// </summary>
public class WebControlOutputPage : Page {
//notify the calling parent the HTML is ready
public event Action<string> Rendered;
//render the output to work with
protected override void Render(HtmlTextWriter writer) {
using (StringWriter output = new StringWriter()) {
using (HtmlTextWriter html = new HtmlTextWriter(output)) {
base.Render(html);
this.Rendered(output.ToString());
}
}
}
}
You will also need an .ASPX page to load your controls with. Make sure it inherits from the WebControlOutputPage class above. Below is an example that will work.
<%@ Page Language="C#" Inherits="WebControlOutputPage" %>
<html>
<head runat="server" />
<body>
<form id="pf" runat="server" />
</body>
</html>
Since this code isn’t the final version I won’t explain too much of it and instead focus on the relevant parts.
A ViewState By Any Other Name Is… Uh…
I personally found HTML to be a little strange when it came to the name and id attributes on certain elements, it seemed to me that those were redundant, but hardly a real issue. In this instance, having the two attributes works to our advantage.
You’ll notice that in our code we append and remove a prefix to the names of the state containers, for example the __VIEWSTATE and __EVENTSTATE, on our page. By doing this, the id remains the same so Javascript can continue to access it but the name changes to avoid being caught as an error in the ViewPage.
You’ll also notice that we create a new HttpRequest and rename the state values to their original name. This allows any state information to slip past the ViewPage, but then be used by the WebControl Form. There is more than likely a better way to do that part, but for now it works — at least for this purpose.
So How About An Example?
The helper methods have changed up a bit to allow the control to be created by a delegate inline. This way it is a little easier to assign event handlers to your controls before they are rendered. Let’s put a simple button on the page.
<html>
<body>
<h2>WebControl Inline With MVC</h2>
<form method="post" >
<% this.RenderWebFormControl(() => {
//create the button
Button test = new Button() {
ID = "myButton"
};
//assign an event
test.Click += (s, e) => {
test.Text += test.Text.Length.ToString();
};
//return the control so it can be used
return test;
}); %>
</form>
</body>
</html>
By using a delegate we’re given a chance to assign a click handler to append some text onto our WebControl. After it is returned in the delegate it is rendered to the page. After we wrap the control with a form and then run it check out what we get.

Success!! Our postback went through and our control is being updated as we wanted — and all inline with our MVC code!!
Not Quite There…
This code works pretty well, but there is a couple problems already. First, we can only have one control per page because each control outputs its own ViewState — so having a Button talk to a TextBox isn’t going work right now. Additionally, code that uses the __doPostback method is going to fail because that method isn’t added to the page yet.
Good news is that we solve those problems in the next post in this series! Hang in there and check back soon!
Testing Your Javascript
I’ve noticed that there has been a lot of talk lately about TDD, or Test Driven Development. Personally, I see it useful in certain areas and not so much in others. But, one thing that I’ve found TDD really great for is Javascript libraries, or really any dynamic language for that matter.
Dynamic languages have a chance of being altered by anything at anytime. It makes them particularly difficult to debug. Have you ever tried this before?
window.alert = document.body; window.alert.innerHTML = "Dude, what?";
Yep, believe it or not, that code actually runs — and works as advertised!
So you’re working on a large Javascript library, how can you test? There is plenty of libraries out there that you can download and use, but for fun we’re going to write our own.
What Makes A Test?
It’s a good question! Basically you take some code from your library, check the results of a method or series of methods and then return back if the test succeeded or not.
That’s an overly simplistic view of a test – but it’s sufficient for this example. Here is some code I wrote for my jLinq tests.
setTimeout(function() {
(function(tests) {
var self = this;
self.index = 0;
self.errors = [];
self.target = document.getElementById("results");
this.assert = function(ok, msg) {
if (ok) { return; }
self.errors.push(msg);
};
var test = function() {
//reset
self.errors = [];
//try the method
try {
//document.body.innerHTML += "<hr/>" + tests[self.index].name;
this.current = tests[self.index].method;
this.current();
}
catch (e) {
self.errors.push("Exception: " + e);
}
//if not okay, display the errors
var result = ["<div class='result result-"];
if (self.errors.length > 0) {
result.push("error' >");
result.push("<div class='result-title'>#" + (self.index + 1) + ": " + tests[self.index].name + "</div>");
result.push("<div class='result-errors' >" + self.errors.join("<br />") + "</div>");
}
else {
result.push("success' >");
result.push("<div class='result-title'>#" + (self.index + 1) + ": " + tests[self.index].name + "</div>");
}
result.push("</div>");
self.target.innerHTML += result.join("");
//set the next test
self.index++;
if (self.index >= tests.length) { return; }
setTimeout(test, 1);
};
//start the tests
test();
})([
//Actual Tests go here
//more explained in a moment
//.......
])}, 250);
What we have created here is a special bit of code that only I know about. I actually invented it just today which I have named a “Recursive Function”.
…oh? You mean that’s been around for awhile now already? Nevermind then…
The code basically calls the same test routine each time, but increments our test index each time. This way all of our tests are completed, but are also done with a slight pause between each to keep our browser from locking up.
Adding A Test
So how do we actually create a test. What do we need to have for this to work? Well since we’re passing in array of tests our code will look something like this
//Rest of the class
//...snip...
})([
//Tests
{name:"Function charAt correctly finds values at indexes",
method:function() {
this.assert("abcd".charAt(0) == "a", "Did not locate correct letter checking start of string");
this.assert("abcd".charAt(3) == "d", "Did not locate correct letter checking end of string");
}},
{name:"Function calculateRate correctly returns percentage based on values",
method:function() {
this.assert(calculateRate(11000) == 0.5, "Did not calculate correct rate from values greater than 10,000");
this.assert(calculateRate(5100) == 0.3, "Did not calculate correct rate from values greater than 5,000");
this.assert(calculateRate(1100) == 0.1, "Did not calculate correct rate from values greater than 1,000");
this.assert(calculateRate(100) == 0, "Did not calculate correct rate from values less than 1,000");
}},
{name:"Runs a function (this test just fails for this blog example)",
method:function() {
this.assert(someFakeFunction(), "We won't see this message");
}}
]);
The tests above are some examples of tests you could write. I’m not an expert on this stuff by any stretch of the imagination, but these tests seem solid enough to tell us if one of our functions fail.
The last example calls a function that doesn’t exist, which in my code, passes the exception along as the error message.
So Why Does This Help
Remember the code sample at the start of the post? Where I just up and changed what window.alert does? Let’s say we had our tests and then somewhere in our code we did this…
String.prototype.charAt = function() { return "a"; }
It’s perfectly legal and it completely breaks what we expect our results to be.
Now, jLinq is 1655 lines of code right now, clearly not a behemoth of a library like jQuery, but large enough that I don’t remember what I wrote everywhere, but now that I have tests it doesn’t matter as much. I’m able to write some changes to the code, run the test and be certain that the library is still in tact. In fact, I wish I would have done it sooner.
What’s Next?
Don’t consider this to be all there is to TDD, but instead a very basic explanation of the concept of TDD. I would recommend to you that if you’re working on large project, especially dynamic languages, make sure you write tests for all of your functions. They will save you in the long run.