Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Sunday, November 27, 2011

More Ajax with MVC – Using Partial Views with Ajax

One the the really nice features in asp.net mvc is the ability to use partial views, not only for breaking up pages and reusing content but also for doing Ajax calls.  In Easy Ajax with ASP.NET MVC and jQuery I showed you how to do a basic Ajax call and display the data returned, now I’m going to show you something a little more useful, actually retuning content to display on the page.
First we take this partial view
   1: @using SampleApplication.Models
   2: @model PartialModel
   3:  
   4: <div>
   5:     @Model.Text
   6: </div>
   7: <input type="button" value="click me" onclick="UpdateView();return false;"/>
Then we add it to the main view like this
   1: <div id="UpdateableContent">
   2:     @{ Html.RenderPartial("Partial",new PartialModel{Text = "Before Clicked"}); }
   3: </div>
Next we need to have a Action to call that returns the rendered view with updates
   1: public ActionResult UpdatePartial()
   2: {
   3:     var model = new PartialModel() {Text = "was updated"};
   4:     return View("Partial", model);
   5: }
In this case we update the model and return the specified partial view with the updated model.

Last we have the Javascript that makes the Ajax call
   1: function UpdateView() {
   2:     var model = { };
   3:     $.post("/home/UpdatePartial",
   4:         model,
   5:         function (data) {
   6:             $("#UpdateableContent").html(data);
   7:         });
   8: }
it’s fairly simple and a lot like what we did in the Easy Ajax post, the major difference is we take the returned rendered partial view and replace the existing rendering of the partial view using JQuery’s .html(),  this replaces the existing content with the passed in content.  This is a very simple and effective way to manipulate your pages.

As always here is the source code for a sample project using it

Monday, January 18, 2010

Unit Testing For Javascript

Recently I had to write some fairly substantial javascript, and in the process I was reminded of how fast javascript, like most scripting languages, and get out of hand really quick. I took a step back and thought why should I work in javascript any different then I do in other language? Just because it’s a scripting language doesn't make it any less valid of a development platform, and I can apply the same design pattern and principles I would with anything else.

So The first thing I did was went looking for a unit testing framework and I found JSUnit. JSUnit is available from http://www.jsunit.net/ and is a port of the JUnit framework to javascript. The entire testing framework and test runner is written in javascript so I can use it anywhere you use javascript and in any development platform(php, ruby, Perl, java, .net, etc).

Getting started I have this javascript function I want to test

   1: function addTwoNumber(x, y) {
   2:     var result = x + y;
   3:     return result;
   4: }

so first I create an html page and add the jsUnitCore.js and my .js file containing this function (almost all of your javascript really should be in .js files for a number of reasons, but that’s another blog post).

   1: <html>
   2:     <head>
   3:         <script language="JavaScript" src="jsUnitCore.js"></script>
   4:         <script language="JavaScript" src="javascriptCode.js"></script>
   5:     </head>
   6:     <body>        
   7:     </body>
   8: </html>

then to add test cases I create functions inside a script tag in the body of the html page like so

   1: <body>
   2:     <script type="text/javascript">
   3:         function test_addTwoNumber_TwoNumbersAreAdded() {
   4:             var result = addTwoNumber(2, 2);
   5:             assertEquals("Adds 2 values together", 4, result);
   6:         }
   7:  
   8:     </script>
   9: </body>
to tag a function as a test, simply start the function off with the text “test” and the test runner will pick it up and run it. The assert is done with the function assertEquals provided by the jsUnitCore.js file and takes 3 prams (test description, expected value, and actual result) and to run the test you simply open the testRunner.html page in the jsunit dir in a browser

image

then add the file location and run the tests, it’s that simple. If you look at the screen shot you will notice that I’m using opera, for what ever reason I couldn’t get the test runner to work in Firefox, every time I would try and run my test file I would get a time out error, The funny thing is it works in IE, Chrome, and Opera just fine, weird.

Saturday, December 12, 2009

Using WCF to build fast and lean web applications

Recently I ran into a problem where I needed to reduce the size of a page, we had a page with a lot of drop down controls that may or my not be used. The problem with this was the size of the html was huge, every one of the controls was fully populated with over 50 items, next the view state was equally huge storing all of that content. The Solution, using WCF to load the control’s content on demand.

Starting off we need to get WCF configured, and this confused me, I had to manually register WCF in IIS, WHAT!! ok to save you the hassle of having to research how to do this, execute c:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe –i and your good to go.

We have two options for populating the dropdowns, you can use a 3rd party control like Telerik’s radcombobox, or roll your own, which in some ways is fairly simple but rather involved, for right now I’m going to show you how to roll your own, to see how to use radComboBox see here.

Lets start with the WCF service, create a Ajax enabled WCF service. For what ever reason I had to remove the namespace to get this to work, and the examples I found online had it removed as well, this is something I’m going to research more on later. Next we need to build a data entity to hold the data, nothing fancy just something like this

   1: public class Item
   2: {
   3:     public string Text { get; set; }
   4:     public string Value { get; set;}
   5: }
   6:  
   7: public class Items : Collection<Item>
   8: {}
next we build the service, in this case I’m just building some data.
   1: [ServiceContract(Namespace = "")]
   2: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   3: public class DataService
   4: {
   5:     [OperationContract]
   6:     public Items GetData()
   7:     {
   8:         Items myItems = new Items();
   9:         for (int i = 0; i < 5; i++)
  10:         {
  11:             Item newItem = new Item()
  12:                {
  13:                    Text = string.Format("value {0}", i), 
  14:                    Value = i.ToString()
  15:                };
  16:             myItems.Add(newItem);
  17:         }
  18:         return myItems;
  19:     }
  20: }
when you add the Ajax enabled WCF service some items will be added to the system.serviceModel section of the web config in this case it looks like this
   1: <system.serviceModel>
   2:   <behaviors>
   3:    <endpointBehaviors>
   4:     <behavior name="DataServiceAspNetAjaxBehavior">
   5:      <enableWebScript />
   6:     </behavior>
   7:    </endpointBehaviors>
   8:   </behaviors>
   9:   <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  10:   <services>
  11:    <service name="DataService">
  12:     <endpoint address="" behaviorConfiguration="DataServiceAspNetAjaxBehavior"
  13:      binding="webHttpBinding" contract="DataService" />
  14:    </service>   
  15:   </services>
  16:  </system.serviceModel>
if your not able to get your service to work with the Namespace, and you remove it, make sure to also remove it from the contract attribute in the endpoint node of the service node.

Next we add the service reference to the page using the script manager tag
   1: <asp:ScriptManager ID="scriptManager" runat="server">
   2:     <Services>
   3:         <asp:ServiceReference Path="/DataService.svc" />
   4:     </Services>
   5: </asp:ScriptManager>
Now we can access the webservice with javascript. First we need to have a dropdown control to work with, for this we are going to just use a plain old html select tag and add an ID and a runat=”server”.
   1: <select 
   2:     id="dropDownList" 
   3:     runat="server" 
   4:     enableviewstate="false" 
   5:     style="width:200px;" 
   6:     onfocus="populateDropDown(this);">
   7: </select>    
something else I have done here is I set enableviewstate="false" this solution doesn't use any view state so for the “cool kids” out there using MVC, this solution works for you as well. Next add the javascript to populate our dropdown, as you can see in the select tag we have a populateDropDown function that is called with onfocus.
   1: var Control;
   2: function populateDropDown(dropdown) {
   3:     Control = dropdown;
   4:     DataService.GetData(dropDownRequest_onSuccess, onFailure);
   5: }
Accessing the service is made easy by using the script manager, all we have to do is call javascript object created by the script manager with the same name as the service contract in this case it’s “DataService” and call the function with the same name as our service method “GetData”. The function takes 2 delegate functions that act as event handlers as parameters, in this case it’s dropDownRequest_onSuccess and onFailure. At this point I would like to say I’m in no way a javascript expert, if you know of a better way to any part of the javascript code by all means do it, and let me know.
   1: var selectedOptionValue;
   2:  
   3: function dropDownRequest_onSuccess(result) {
   4:     Control.options.length = 0;
   5:     for (var x = 0; x < result.length; x++) {
   6:         var opt = document.createElement("option");
   7:         opt.text = result[x].Text;
   8:         opt.value = result[x].Value;
   9:         if (result[x].Value == selectedOptionValue) {
  10:             opt.setAttribute("selected", "true");
  11:         }
  12:         Control.options.add(opt);
  13:     }
  14: }
  15:  
  16: function onFailure(result) {
  17:     window.alert(result);
  18: }
The dropDownRequest_onSuccess function clears (if any) options from the select tag, then loops though the result from the webservice, creating option elements, setting their text and value then checking to see if the value matches the value of the selectedOptionValue var and if they do it sets that option as selected then adds it to the options collection of the select control.

The onFailure is called when the service call fails, and for this we are just doing a simple alert to say it failed.

The next part is getting the data out when the page is submitted, because we are not using any view state we can’t get the value the same way we would with a regular asp.net control, we have to pull it from Request.Form collection.
   1: string value = Request.Form[dropDownList.ID];
Finally we need to add a way to set an option as selected. The code to set the selected option is already there we just have to utilize it by setting the value of var selectedOptionValue, to do this we use the ClientScript.RegisterStartupScript like this
   1: private void setValue()
   2: {
   3:     string script = string.Format("setpopulateDropdown('{0}',{1});", dropDownList.ClientID, Request.Form[dropDownList.ID]);
   4:     ClientScript.RegisterStartupScript(typeof(Page),"setDropdownValue",script,true);
   5:     
   6: }

to call this javascript function

   1: function setpopulateDropdown(controlId, value) {
   2:     Control = document.getElementById(controlId);
   3:     selectedOptionValue = value;
   4:     populateDropDown(Control);
   5: }

This sets the control to be updated, set the selected value, then populates the the control from the webservice.

Like I said it’s kind of a long process but you can cut down your page size a lot if your doing multiple dropdowns with large amounts of data that may not be used.

As always the full source code for this project is available (here).