Search Results

Search found 25257 results on 1011 pages for 'jquery css'.

Page 172/1011 | < Previous Page | 168 169 170 171 172 173 174 175 176 177 178 179  | Next Page >

  • I lost my CSS Codes of my important Website, Why?

    - by Hooshkar
    Very weird, i had opened notepad ++ and working on my CSS codes for my website, suddenly my little niece unplugged the computer, when i re-start the computer and opened again the same CSS codes file in notepad ++, so all i am seeing is "NULL NULL NULL NULL NULL NULL NULL" there is no codes, all lost. I opened the same CSS codes file in other editors and its all empty no codes.. is there a way to fix it, because it was my hard work. and what can be the cause? Thank you.

    Read the article

  • What are the drawbacks of using PHP to create variables in my CSS stylesheet?

    - by Greg
    One significant drawback of CSS is that one can't use variables. For example, I'd like to use variables to control the location of imported CSS, and it would be awesome to create variables for colors that are used repeatedly in a design. One approach is to use a PHP file for the CSS stylesheet. In other words, create a "style.php" with... <?php header("Content-type: text/css"); ?> ...at the top of the file, and then link to it using... <link href="style.php" rel="stylesheet" type="text/css" /> ...in any file that uses these styles. So what's the catch? I think it might be performance -- I did a few quick experiments in Firefox/Firebug and as one would expect, the CSS stylesheet is cached, but the PHP stylesheet isn't. So we're paying the price of an additional GET. The other annoying thing is that TextMate does not syntax highlight properly for CSS in a .php file. Are there other drawbacks? Have you used this approach, and if so, would you recommend it?

    Read the article

  • Ajax Talk at .NET Developers Association

    - by Stephen Walther
    Thanks everyone who came to my Ajax talk tonight at the .NET Developers Association! The slides and demos from the talk can be downloaded by clicking the following link:   ASP.NET Ajax: What’s New?    You need Visual Studio  2010 to view the code samples. The first project, named Demos, contains the following samples: ASPAjax4 1_CompositeScripts.aspx – Demonstrates how to use the ScriptManger to combine, compress, and cache JavaScript files automatically. 2_EnableCdn.aspx – Demonstrates how to retrieve ASP.NET Ajax framework scripts from the Microsoft Ajax CDN automatically. jQuery 1_Selectors.aspx – Demonstrates how to use jQuery selectors 2_WebForms.aspx – Demonstrates how to use the client tablesorter plugin with ASP.NET Web Forms. 3_MVC.aspx – Demonstrates how to use jQuery animation and the templating plugin with ASP.NET MVC. 4_OData.aspx – Demonstrates how to use jQuery with the Netflix API by using JSONP and odata. 5_Templating.aspx – Demonstrates how to use jQuery client templating. 6_TemplateConditionals.aspx – Demonstrates how to use logic within a jQuery template. 7_DataLinking.aspx – Demonstrates how to perform data-binding in jQuery. 8_Converters.aspx – Demonstrates how to defines converters that work with data-binding. The second project, named ACT_Tools, illustrates how to use the Microsoft Ajax Minifier and the JSBuild JavaScript preprocessor. When you perform a build in Visual Studio, all JavaScript and CSS files are minified automatically. Furthermore, any *.pre.js file is processed using the JSBuild preprocessor and the output is saved to the ScriptOutput folder. Select Show All Files in Visual Studio to see the generated results of the minifier and the preprocessor.

    Read the article

  • Slider Position

    - by RobinHood
    I had used this code for to create a slider. It's working fine. I want to place the slider next to my label control. Like this (Slidder : Slidder Bar) How to do that? <div> <tr> <td class="aln-rht"> <asp:Label ID="Literal4" runat="server" Text="Slidder :" Font-Bold="true" /> </td> <td> <%=Html.DropDownList("Scale", null, "--Select Scale--", new { id = "speed1" , Style = "display:none"})%> </td> </tr> </div> <script type="text/javascript"> $(function () { var abc = $('select#speed1').selectToUISlider().next(); fixToolTipColor(); }); function fixToolTipColor() { $('.ui-tooltip-pointer-down-inner').each(function () { var bWidth = $('.ui-tooltip-pointer-down-inner').css('borderTopWidth'); var bColor = $(this).parents('.ui-slider-tooltip').css('backgroundColor') $(this).css('border-top', bWidth + ' Solid ' + bColor); }); } </script> The ui.slider.extras.css, selectToUISlider.JQuery.js and ui.slider.js files I had used This is JQuery-ui-1.7.1.custom.css, which i am using... .ui-slider { position: relative; text-align: left; } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; border-color: Maroon; background-color: Olive} .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } .ui-slider-horizontal { height: .8em; border-color: Olive;} .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } .ui-slider-horizontal .ui-slider-range-min { left: 0; } .ui-slider-horizontal .ui-slider-range-max { right: 0; } .ui-slider-vertical { width: .8em; height: 100px; border-color: Olive; } .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } .ui-slider-vertical .ui-slider-range-min { bottom: 0; } .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs

    Read the article

  • Appcache and jquery mobile on a CMS powered site?

    - by user793011
    Has anyone used the cache manifest to make a CMS site work offline? I've made a demo with static html files which seems to work fine, so I'm assuming it wouldn't be too hard to achieve the same thing with a CMS. The way that you tell browsers that files have changed (and so need to be downloaded again) is by adding a comment to the cache manifest file so its byte size changes. I'm not quite sure how to do this with a CMS, but maybe some sort of server cron could run periodically? Personally I'm more interested in having a site that works offline rather than achieving ideal performance, so if the file was modified every hour rather than when content actually changed that would be fine for me. If anyone has used appcache with a CMS, has anyone done so with jquery mobile at the same time? What I'm after is a fully native feel to a site that's accessible offline, in other words I want to mimic a native App. My static demo does this perfectly with jquery mobile, so again I would have thought this would be achievable in a CMS.

    Read the article

  • Top Container Background Problem

    - by Norbert
    Here's a screenshot: http://dl.getdropbox.com/u/118004/Screen%20shot%202010-04-13%20at%202.50.49%20PM.png The red bar on the left is the background I set for the #personal div and I would like it to align to the top of the container, vertically. The problem is that I have a background for the #container-top div on top of the #container div with absolute positioning. Is there any way to move the #personal div up so there would be no space left? HTML <div id="container"> <div id="container-top"></div> <div id="personal"> <h1>Jonathan Doe</h1> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliqua erat volutpat.</p> </div> <!-- end #personal --> </div> <!-- end #container --> CSS #container { background: url(images/bg-mid.png) repeat-y top center; width: 835px; margin: 40px auto; position: relative; } #container-top { background: url(images/bg-top.png) no-repeat top center; position: absolute; height: 12px; width: 835px; top: -12px; } #container-bottom { background: url(images/bg-bottom.png) no-repeat top center; position: absolute; height: 27px; width: 835px; bottom: -27px; } #personal { background: url(images/personal-info.png) no-repeat 0px left; }

    Read the article

  • Positioning one div to the right of another

    - by Jonno_FTW
    Hi I have the following html and css. But what I can't figure out is how to have the tabs div at the right of the main div. So that they stick out the right like bookmarks. .main { -moz-border-radius:10px; height: 75%; width: 60%; position: absolute; top: 15%; left: 20%; right: auto; } .tabs { width: 50px; height: 1.3em; position: absolute; float: right; } #tab { margin: 10px 10px 10px 0px;} And the html: <div class="main"> <div id="content"> Some main content </div> </div> <div class="tabs"> <div class="tabs" id="tab"> <a href="#" alt="Home"> Home </a> </div> <div class="tabs" id="tab"> <a href="#" alt="About"> About </a> </div>

    Read the article

  • Dynamic columns/rows

    - by Fuego DeBassi
    Wondering--does anyone know of any good articles explaining the CSS technique allowing multiple instances of a class to flow down the page relative to the items above it. Not explaining it that well. Veerle' Pierter's does it on this page: http://veerle.duoh.com/belgiangraphicdesign Although I'm not sure I want to use a technique like her's that requires entering of the height per element via her EE installation. I made a little graphic of what I am trying to acheive; http://cl.ly/71163510ce9d294f9f33 The key is I need a robust technique for doing it. Something where the markup could be as simple as; <div class="box"> Number 1 </div> <div class="box"> Number 2 </div> <div class="box"> Number 3 </div> <div class="box"> Number 4 </div> <div class="box"> Number 5 </div> ... Would love any pointers in the right direction.

    Read the article

  • Dynamic margin (or simulation of margin) between left floated divs

    - by BugBusterX
    I have a number of divs floated left. When browser is resized they move down or up based on how many can fit on the line. I was wondering if there is a way to dynamically (with css) have those divs align (or have margin) in a way, that they would always fill the entire screen space by having their marhin resize? In other words margin between them would resize while browser is resized, but as soon as another div can fit it will be added in the line, or if minimum margin is reached and passed another div goes to next line while margins expand again. Here's an example how it is now, resize the wondow to see he leftover space that I want to "fill" <html> <head> <style> .test { float:left; width: 100px; height:100px; background-color: grey; margin: 0 10px 10px 0; } </style> </head> <body> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> <div class="test"></div> </body> </html>

    Read the article

  • Reducing the opacity on a div without reducing the opacity of the contents

    - by user352744
    Want to reduce the opacity of page contents container background without reducing the opacity of the contents. <div id="container"> <div id="page contents"> page contents goes here, like amazing articles and all that. </div> </div> Needs to be able to expand with the content, thus can't have a fixed height. Absolute positioning it underneath the content will mean there will be no relationship between the two divs and it wont expand with the contents, so I think this is a dead end, feel free to say otherwise. Can't use Jquery as could be too laggy and not instant. Other options preferred please. May have to use 'png' background images but were hoping not to as it is a template and needs to be able to change colour based on colour schemes. Could generate images on demand but not ideal. Oh and to top it off cant use CSS3 as wont work in IE! of course! Any suggestions?

    Read the article

  • Aligning decimal points in HTML

    - by ijw
    I have a table containing decimal numbers in one column. I'm looking to align them in a manner similar to a word processor's "decimal tab" feature, so that all the points sit on a vertical line. I have two possible solutions at the moment but I'm hoping for something better... Solution 1: Split the numbers within the HTML, e.g. <td><div>1234</div><div class='dp'>.5</div></td> with .dp { width: 3em; } (Yes, this solution doesn't quite work as-is. The concept is, however, valid.) Solution 2: I found mention of <COL ALIGN="CHAR" CHAR="."> This is part of HTML4 according to the reference page, but it doesn't work in FF3.5, Safari 4 or IE7, which are the browsers I have to hand. It also has the problem that you can't pull out the numeric formatting to CSS (although, since it's affecting a whole column, I suppose that's not too surprising). Thus, anyone have a better idea?

    Read the article

  • How to bring the parent element with floated child elements to the center of the document?

    - by Starx
    I have organized a menu. Its HTML is as follows: <ul class="topmenu"> <li><a href="sample.html">Text 1</a></li> <li><a href="sample.html">Text 2</a></li> <li><a href="sample.html">Text 3</a></li> <li><a href="sample.html">Text 4</a></li> <ul> This is a horizontal menu, so I have floated the list items to left to appear them in a horizontal line. I could have used display:inline to appear them in a single line, but since IE does not support it and I don't know any other way to do so, I used float:left;. It's css is: .topmenu { list-style:none; margin:0; padding:0; } .topmenu li { float:left; } This brings the menu in a perfect horizontal line, but the entire list is floated to the left. I want to bring the .topmenu to appear in the center of the document and keep the listitem inside it floated towards the left. I found that this is achievable by defining width property of the .topmenu, but I dont want to fix its width as the list-items are dynamically generated and thus could increase and decrease. Any one know of any solution?

    Read the article

  • Floats being pushed down in IE8 but not IE7 or Firefox

    - by BReno
    The page in question is here: http://supportdogs.digitalportals.net/PhotoGallery/16-Events You can see in IE8 that the content is being pushed down under the sidebar. If you view it in IE8 compatibility mode, it doesn't happen, nor does it happen in Firefox. If you browse to a different page in IE8 the issue does not persist. The basic layout is <div class="contentContainer"> <div class="left"></div> <div class="right"></div> </div> The css for those three classes is here #contentContainer { background: transparent url('../images/bodyBG.png') repeat-y center top; clear: both; padding: 0px 30px 0px 30px; margin-top: 83px; width: 935px; } #contentContainer .left { float: left; margin-top: 60px; padding-left: 5px; width: 195px; } #contentContainer .right { float: right; margin: -55px 0px 20px 0px; min-height: 620px; width: 700px; } Anyone have any idea what could be causing this?

    Read the article

  • Anchors with overlapping divs

    - by tmdelane
    I am using a grid based layout, with two main sections. Graph and Timeline. Graph, contains graded vertical bars, HTML similar to: <div id="graph" class="container_160"> <div id="Jan-97" class="grid_1 major"><a href="#">&nbsp;</a></div> <div id="Feb-97" class="grid_1 minor"><a href="#">&nbsp;</a></div> <div id="Mar-97" class="grid_1 minor"><a href="#">&nbsp;</a></div> <div id="Apr-97" class="grid_1 minor"><a href="#">&nbsp;</a></div> <div id="May-97" class="grid_1 minor"><a href="#">&nbsp;</a></div> etc... </div> Timeline, contains horizontal bars, HTML similar to: <div id="timeline" class="container_160"> <div id="bar1" class="grid_32 suffix_128"><a href="#">&nbsp;</a></div> <div id="bar2" class="prefix_32 grid_24 suffix_104"><a href="#">&nbsp;</a></div> <div id="bar3" class="prefix_58 grid_7 suffix_95"><a href="#">&nbsp;</a></div> </div> Timeline is relatively positioned to Graph so that it overlaps. My problem is that when these divs overlap, the anchors in Timeline stop working. I am open to both CSS and Jquery solutions. Thanks in advance. t.

    Read the article

  • Centered DIV w/ width dependant on text, buffered by two divs that should fill the containing DIV

    - by Andrew Thompson
    I have been wracking my brains on this seemingly small issue the whole day. My web dev friends are baffled and I could not find a suitable answer in my search of this site and others (though, I could have missed it somewhere along the way). Here's the problem: 3 DIVS within one fixed-width container DIV The center DIV has text that will be different on other sites The center DIV needs to be centered, and no larger than the text it contains. This is what I'd like to end up with The basic HTMl: <div id="container" > <div id="left" ></div> <div id="center" >Text inside center should resize this block</div> <div id="right" ></div> </div> Below, I removed most of the styles I have tried. This CSS currently centers the DIV (if I set it as an inline block), but I need the other divs to fill the left and right space remaining: #container { width:750px; text-align:center; } #left { background-color:#E85355; } #center { background-color:#CDD7D7; display:inline-block; } #right { background-color:#65A8A6; } I've tried floating, no-wrap, overflow, etc. Thanks a million to whomever can offer some help! JSFiddle Link

    Read the article

  • Blockquote border on tumblr theme

    - by orange
    This is the code for the link block: {block:Link} <div class="post link"> <h2> <a href="{URL}" class="name">{Name}</a></h2> <div class="content"> {block:Description}{Description}{/block:Description} <span class="date"> <a href="{Permalink}">{ShortMonth} {DayOfMonth}, {Year} </a> </span> </div> </div> {/block:Link} What I'm trying to do is add a border-left of of 10px to block quotes. When I try to add this style to block quotes this happens: The block quote border flows into the post title and I don't wish for this to happen, I want the border layout to stay within the content div. I'm using this CSS at the moment: div div div blockquote { border-left: 10px solid red; } Thanks in advance for the help! Just to clarify <div class="post link"> is in another div. Here is the tumblr: http://iamsomething-awesome.tumblr.com/

    Read the article

  • using same ids for many tags?

    - by gaurav rathor
    here is the example code that i was testing and i got confused that every one says that we can use or we should use only one time per id but i have testes using using it multiple times but its giving me the correct output. so what should i do. it is kinda working same like class for me in this example code: <html> <head> <style> #exampleID1 { background-color: blue; } #exampleID2 { text-transform: uppercase; } </style> </head> <body> <p id="exampleID1">This paragraph has an ID name of "exampleID1" and has a blue CSS defined background.</p> <p id="exampleID2">This paragraph has an ID name of "exampleID2" and has had its text transformed to uppercase letters.</p> <address id="exampleID1"> Written by W3Schools.com<br /> <a href="mailto:[email protected]">Email us</a><br /> Address: Box 564, Disneyland<br /> Phone: +12 34 56 78 </address> <blockquote id="exampleID1"> Here is a long quotation here is a long quotation here is a long quotation here is a long quotation here is a long quotation here is a long quotation here is a long quotation here is a long quotation here is a long quotation. </blockquote> </body> </html> please see the above code and answer me that why we should not use id selector two times in a page while its working fine.

    Read the article

  • Is there a selector or a work around to select any element with no children.

    - by rnaud
    Looking at the CSS3 specs, I can't find any way to select any element that has no children. Let me explain. <body> <h1>Main Page</h1> <div id="main"> <div class="post"> <h2>Article 1</h1> <p>some text</p> </div> <div class="post"> <h2>Article 2</h1> <p>some text</p> </div> </div> </body> I'm looking for a CSS syntax to select the h1, the two h2 and the two p. A way to select in any page, all elements with no children. Any suggestion ? Sorry, I forgot to add the "empty" part, I am actually already using the *:empty selector, but it's not working for any tag that has a nodeText as a child. So it's working for any input, image, object, but not for h2, h1, or any p.

    Read the article

  • Why doesn't my <div> float around another floated <div> while other elements do?

    - by user1848605
    I have a container with background color green. Inside that green <div>, I have a <div> which is black and styled as a box (50px x 50px) - this <div> is floated to the left. Now if I add a <p> to my markup after the grey <div>, I'd expect it to float around the grey <div>. And it does. However, when I substitue with another <div> which is styled as box (set height and width), it doesn't float around anymore, but disappears behind the floating div. Even if I have first paragraphs which are floating around correctly and THEN I add the div (box), the paragraphs stop floating around and appear on another line. HTML: <div id="greencontainer"> <div id="blackbox"></div> <!--this one is float:left;--> <p>A paragraph that floats around the previous div</p> <div id="anotherbox"></div> <!-- if I add another div with set width and height, it disappears behind the floated one, and even prevents the paragraph from floating around.--> </div> CSS: #blackbox { width:50px; height:50px; background-color:black; float:left; } #p { margin:0px; padding:0px; } #anotherbox { width:50px; height:50px; background-color:grey; }

    Read the article

  • Use a table as container or not?

    - by Camran
    I have created my entire website by using a main table, and having the content inside the table. Some ppl suggest this is wrong, and I would like to know what to do specifically in my situation. On my index.html I have a <table align="center"> and then all content in it. Now the content is in form of DIVS and they all have relative positioning, so they are relative to the table. For example: <table align="center"> <tr> <td> <div style="position:relative; left:14px; top:50px;"> CONTENT HERE... (Form, divs, images) </div> </td> </tr> </table> I have just gotten to the stage of browser compatibility. Without making any changes whatsoever, my website works perfect in FF, SAFARI, Chrome and Opera. Only trouble with IE. So for my Q, if you where me, would you change my layout and remove the tables, and instead use alot more css and alot more DIVS, or would you go with what I have? And please if you answer me, don't just provide me with the answer, but also a "why" that is... in other words, give me arguments and facts... Thanks

    Read the article

  • Internet Explorer 6 and 7: floated elements expand to 100% width when they contain a child element f

    - by Paul D. Waite
    I've got a parent div floated left, with two child divs that I need to float right. The parent div should (if I understand the spec correctly) be as wide as needed to contain the child divs, and this is how it behaves in Firefox et al. In IE, the parent div expands to 100% width. This seems to be an issue with floated elements that have children floated right. Test page: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>Float test</title> </head> <body> <div style="border-top:solid 10px #0c0;float:left;"> <div style="border-top:solid 10px #00c;float:right;">Tester 1</div> <div style="border-top:solid 10px #c0c;float:right;">Tester 2</div> </div> </body> </html> Unfortunately I can't fix the width of the child divs, so I can't set a fixed width on the parent. Is there a CSS-only workaround to make the parent div as wide as the child divs?

    Read the article

  • How do I size a second div to be 100% height underneath a fixed image?

    - by mk
    I'm using semi-transparent PNGs (due to the designer's overlapping of elements) and trying to achieve a layout that represents the design while still working well on the web. Thus I have simple HTML: <div id="right"> <div id="welcome"></div> <div id="welcomeRepeatingBottom"></div> </div> And I'm trying to use CSS as follows: #right { height: 100%; position: absolute; right: 0px; top: 0px; width: 430px; } #welcome { background-image: url("welcome.png"); height: 614px; width: 430px; position: absolute; top: 0px; left: 0px; } #welcomeRepeatingBottom { background: url("welcomeBottom.png") repeat-y; height: 100%; left: 0px; position: absolute; top: 614px; width: 430px; } The problem is...the #welcomeRepeatingBottom div can't overlap the #welcome div because of the transparency. What I really want is the #welcomeRepeatingBottom div to be height: 100% - 614px, but of course you can't do that. Am I missing something here or do I need to manipulate these values with JavaScript/JQuery?

    Read the article

  • Introduction to the ASP.NET Web API

    - by Stephen.Walther
    I am a huge fan of Ajax. If you want to create a great experience for the users of your website – regardless of whether you are building an ASP.NET MVC or an ASP.NET Web Forms site — then you need to use Ajax. Otherwise, you are just being cruel to your customers. We use Ajax extensively in several of the ASP.NET applications that my company, Superexpert.com, builds. We expose data from the server as JSON and use jQuery to retrieve and update that data from the browser. One challenge, when building an ASP.NET website, is deciding on which technology to use to expose JSON data from the server. For example, how do you expose a list of products from the server as JSON so you can retrieve the list of products with jQuery? You have a number of options (too many options) including ASMX Web services, WCF Web Services, ASHX Generic Handlers, WCF Data Services, and MVC controller actions. Fortunately, the world has just been simplified. With the release of ASP.NET 4 Beta, Microsoft has introduced a new technology for exposing JSON from the server named the ASP.NET Web API. You can use the ASP.NET Web API with both ASP.NET MVC and ASP.NET Web Forms applications. The goal of this blog post is to provide you with a brief overview of the features of the new ASP.NET Web API. You learn how to use the ASP.NET Web API to retrieve, insert, update, and delete database records with jQuery. We also discuss how you can perform form validation when using the Web API and use OData when using the Web API. Creating an ASP.NET Web API Controller The ASP.NET Web API exposes JSON data through a new type of controller called an API controller. You can add an API controller to an existing ASP.NET MVC 4 project through the standard Add Controller dialog box. Right-click your Controllers folder and select Add, Controller. In the dialog box, name your controller MovieController and select the Empty API controller template: A brand new API controller looks like this: using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Web.Http; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { } } An API controller, unlike a standard MVC controller, derives from the base ApiController class instead of the base Controller class. Using jQuery to Retrieve, Insert, Update, and Delete Data Let’s create an Ajaxified Movie Database application. We’ll retrieve, insert, update, and delete movies using jQuery with the MovieController which we just created. Our Movie model class looks like this: namespace MyWebAPIApp.Models { public class Movie { public int Id { get; set; } public string Title { get; set; } public string Director { get; set; } } } Our application will consist of a single HTML page named Movies.html. We’ll place all of our jQuery code in the Movies.html page. Getting a Single Record with the ASP.NET Web API To support retrieving a single movie from the server, we need to add a Get method to our API controller: using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using MyWebAPIApp.Models; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { public Movie GetMovie(int id) { // Return movie by id if (id == 1) { return new Movie { Id = 1, Title = "Star Wars", Director = "Lucas" }; } // Otherwise, movie was not found throw new HttpResponseException(HttpStatusCode.NotFound); } } } In the code above, the GetMovie() method accepts the Id of a movie. If the Id has the value 1 then the method returns the movie Star Wars. Otherwise, the method throws an exception and returns 404 Not Found HTTP status code. After building your project, you can invoke the MovieController.GetMovie() method by entering the following URL in your web browser address bar: http://localhost:[port]/api/movie/1 (You’ll need to enter the correct randomly generated port). In the URL api/movie/1, the first “api” segment indicates that this is a Web API route. The “movie” segment indicates that the MovieController should be invoked. You do not specify the name of the action. Instead, the HTTP method used to make the request – GET, POST, PUT, DELETE — is used to identify the action to invoke. The ASP.NET Web API uses different routing conventions than normal ASP.NET MVC controllers. When you make an HTTP GET request then any API controller method with a name that starts with “GET” is invoked. So, we could have called our API controller action GetPopcorn() instead of GetMovie() and it would still be invoked by the URL api/movie/1. The default route for the Web API is defined in the Global.asax file and it looks like this: routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); We can invoke our GetMovie() controller action with the jQuery code in the following HTML page: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Get Movie</title> </head> <body> <div> Title: <span id="title"></span> </div> <div> Director: <span id="director"></span> </div> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> getMovie(1, function (movie) { $("#title").html(movie.Title); $("#director").html(movie.Director); }); function getMovie(id, callback) { $.ajax({ url: "/api/Movie", data: { id: id }, type: "GET", contentType: "application/json;charset=utf-8", statusCode: { 200: function (movie) { callback(movie); }, 404: function () { alert("Not Found!"); } } }); } </script> </body> </html> In the code above, the jQuery $.ajax() method is used to invoke the GetMovie() method. Notice that the Ajax call handles two HTTP response codes. When the GetMove() method successfully returns a movie, the method returns a 200 status code. In that case, the details of the movie are displayed in the HTML page. Otherwise, if the movie is not found, the GetMovie() method returns a 404 status code. In that case, the page simply displays an alert box indicating that the movie was not found (hopefully, you would implement something more graceful in an actual application). You can use your browser’s Developer Tools to see what is going on in the background when you open the HTML page (hit F12 in the most recent version of most browsers). For example, you can use the Network tab in Google Chrome to see the Ajax request which invokes the GetMovie() method: Getting a Set of Records with the ASP.NET Web API Let’s modify our Movie API controller so that it returns a collection of movies. The following Movie controller has a new ListMovies() method which returns a (hard-coded) collection of movies: using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using MyWebAPIApp.Models; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { public IEnumerable<Movie> ListMovies() { return new List<Movie> { new Movie {Id=1, Title="Star Wars", Director="Lucas"}, new Movie {Id=1, Title="King Kong", Director="Jackson"}, new Movie {Id=1, Title="Memento", Director="Nolan"} }; } } } Because we named our action ListMovies(), the default Web API route will never match it. Therefore, we need to add the following custom route to our Global.asax file (at the top of the RegisterRoutes() method): routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); This route enables us to invoke the ListMovies() method with the URL /api/movie/listmovies. Now that we have exposed our collection of movies from the server, we can retrieve and display the list of movies using jQuery in our HTML page: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>List Movies</title> </head> <body> <div id="movies"></div> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> listMovies(function (movies) { var strMovies=""; $.each(movies, function (index, movie) { strMovies += "<div>" + movie.Title + "</div>"; }); $("#movies").html(strMovies); }); function listMovies(callback) { $.ajax({ url: "/api/Movie/ListMovies", data: {}, type: "GET", contentType: "application/json;charset=utf-8", }).then(function(movies){ callback(movies); }); } </script> </body> </html>     Inserting a Record with the ASP.NET Web API Now let’s modify our Movie API controller so it supports creating new records: public HttpResponseMessage<Movie> PostMovie(Movie movieToCreate) { // Add movieToCreate to the database and update primary key movieToCreate.Id = 23; // Build a response that contains the location of the new movie var response = new HttpResponseMessage<Movie>(movieToCreate, HttpStatusCode.Created); var relativePath = "/api/movie/" + movieToCreate.Id; response.Headers.Location = new Uri(Request.RequestUri, relativePath); return response; } The PostMovie() method in the code above accepts a movieToCreate parameter. We don’t actually store the new movie anywhere. In real life, you will want to call a service method to store the new movie in a database. When you create a new resource, such as a new movie, you should return the location of the new resource. In the code above, the URL where the new movie can be retrieved is assigned to the Location header returned in the PostMovie() response. Because the name of our method starts with “Post”, we don’t need to create a custom route. The PostMovie() method can be invoked with the URL /Movie/PostMovie – just as long as the method is invoked within the context of a HTTP POST request. The following HTML page invokes the PostMovie() method. <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Create Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToCreate = { title: "The Hobbit", director: "Jackson" }; createMovie(movieToCreate, function (newMovie) { alert("New movie created with an Id of " + newMovie.Id); }); function createMovie(movieToCreate, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify( movieToCreate ), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { callback(newMovie); } } }); } </script> </body> </html> This page creates a new movie (the Hobbit) by calling the createMovie() method. The page simply displays the Id of the new movie: The HTTP Post operation is performed with the following call to the jQuery $.ajax() method: $.ajax({ url: "/api/Movie", data: JSON.stringify( movieToCreate ), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { callback(newMovie); } } }); Notice that the type of Ajax request is a POST request. This is required to match the PostMovie() method. Notice, furthermore, that the new movie is converted into JSON using JSON.stringify(). The JSON.stringify() method takes a JavaScript object and converts it into a JSON string. Finally, notice that success is represented with a 201 status code. The HttpStatusCode.Created value returned from the PostMovie() method returns a 201 status code. Updating a Record with the ASP.NET Web API Here’s how we can modify the Movie API controller to support updating an existing record. In this case, we need to create a PUT method to handle an HTTP PUT request: public void PutMovie(Movie movieToUpdate) { if (movieToUpdate.Id == 1) { // Update the movie in the database return; } // If you can't find the movie to update throw new HttpResponseException(HttpStatusCode.NotFound); } Unlike our PostMovie() method, the PutMovie() method does not return a result. The action either updates the database or, if the movie cannot be found, returns an HTTP Status code of 404. The following HTML page illustrates how you can invoke the PutMovie() method: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Put Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToUpdate = { id: 1, title: "The Hobbit", director: "Jackson" }; updateMovie(movieToUpdate, function () { alert("Movie updated!"); }); function updateMovie(movieToUpdate, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify(movieToUpdate), type: "PUT", contentType: "application/json;charset=utf-8", statusCode: { 200: function () { callback(); }, 404: function () { alert("Movie not found!"); } } }); } </script> </body> </html> Deleting a Record with the ASP.NET Web API Here’s the code for deleting a movie: public HttpResponseMessage DeleteMovie(int id) { // Delete the movie from the database // Return status code return new HttpResponseMessage(HttpStatusCode.NoContent); } This method simply deletes the movie (well, not really, but pretend that it does) and returns a No Content status code (204). The following page illustrates how you can invoke the DeleteMovie() action: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Delete Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> deleteMovie(1, function () { alert("Movie deleted!"); }); function deleteMovie(id, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify({id:id}), type: "DELETE", contentType: "application/json;charset=utf-8", statusCode: { 204: function () { callback(); } } }); } </script> </body> </html> Performing Validation How do you perform form validation when using the ASP.NET Web API? Because validation in ASP.NET MVC is driven by the Default Model Binder, and because the Web API uses the Default Model Binder, you get validation for free. Let’s modify our Movie class so it includes some of the standard validation attributes: using System.ComponentModel.DataAnnotations; namespace MyWebAPIApp.Models { public class Movie { public int Id { get; set; } [Required(ErrorMessage="Title is required!")] [StringLength(5, ErrorMessage="Title cannot be more than 5 characters!")] public string Title { get; set; } [Required(ErrorMessage="Director is required!")] public string Director { get; set; } } } In the code above, the Required validation attribute is used to make both the Title and Director properties required. The StringLength attribute is used to require the length of the movie title to be no more than 5 characters. Now let’s modify our PostMovie() action to validate a movie before adding the movie to the database: public HttpResponseMessage PostMovie(Movie movieToCreate) { // Validate movie if (!ModelState.IsValid) { var errors = new JsonArray(); foreach (var prop in ModelState.Values) { if (prop.Errors.Any()) { errors.Add(prop.Errors.First().ErrorMessage); } } return new HttpResponseMessage<JsonValue>(errors, HttpStatusCode.BadRequest); } // Add movieToCreate to the database and update primary key movieToCreate.Id = 23; // Build a response that contains the location of the new movie var response = new HttpResponseMessage<Movie>(movieToCreate, HttpStatusCode.Created); var relativePath = "/api/movie/" + movieToCreate.Id; response.Headers.Location = new Uri(Request.RequestUri, relativePath); return response; } If ModelState.IsValid has the value false then the errors in model state are copied to a new JSON array. Each property – such as the Title and Director property — can have multiple errors. In the code above, only the first error message is copied over. The JSON array is returned with a Bad Request status code (400 status code). The following HTML page illustrates how you can invoke our modified PostMovie() action and display any error messages: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Create Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToCreate = { title: "The Hobbit", director: "" }; createMovie(movieToCreate, function (newMovie) { alert("New movie created with an Id of " + newMovie.Id); }, function (errors) { var strErrors = ""; $.each(errors, function(index, err) { strErrors += "*" + err + "\n"; }); alert(strErrors); } ); function createMovie(movieToCreate, success, fail) { $.ajax({ url: "/api/Movie", data: JSON.stringify(movieToCreate), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { success(newMovie); }, 400: function (xhr) { var errors = JSON.parse(xhr.responseText); fail(errors); } } }); } </script> </body> </html> The createMovie() function performs an Ajax request and handles either a 201 or a 400 status code from the response. If a 201 status code is returned then there were no validation errors and the new movie was created. If, on the other hand, a 400 status code is returned then there was a validation error. The validation errors are retrieved from the XmlHttpRequest responseText property. The error messages are displayed in an alert: (Please don’t use JavaScript alert dialogs to display validation errors, I just did it this way out of pure laziness) This validation code in our PostMovie() method is pretty generic. There is nothing specific about this code to the PostMovie() method. In the following video, Jon Galloway demonstrates how to create a global Validation filter which can be used with any API controller action: http://www.asp.net/web-api/overview/web-api-routing-and-actions/video-custom-validation His validation filter looks like this: using System.Json; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace MyWebAPIApp.Filters { public class ValidationActionFilter:ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var modelState = actionContext.ModelState; if (!modelState.IsValid) { dynamic errors = new JsonObject(); foreach (var key in modelState.Keys) { var state = modelState[key]; if (state.Errors.Any()) { errors[key] = state.Errors.First().ErrorMessage; } } actionContext.Response = new HttpResponseMessage<JsonValue>(errors, HttpStatusCode.BadRequest); } } } } And you can register the validation filter in the Application_Start() method in the Global.asax file like this: GlobalConfiguration.Configuration.Filters.Add(new ValidationActionFilter()); After you register the Validation filter, validation error messages are returned from any API controller action method automatically when validation fails. You don’t need to add any special logic to any of your API controller actions to take advantage of the filter. Querying using OData The OData protocol is an open protocol created by Microsoft which enables you to perform queries over the web. The official website for OData is located here: http://odata.org For example, here are some of the query options which you can use with OData: · $orderby – Enables you to retrieve results in a certain order. · $top – Enables you to retrieve a certain number of results. · $skip – Enables you to skip over a certain number of results (use with $top for paging). · $filter – Enables you to filter the results returned. The ASP.NET Web API supports a subset of the OData protocol. You can use all of the query options listed above when interacting with an API controller. The only requirement is that the API controller action returns its data as IQueryable. For example, the following Movie controller has an action named GetMovies() which returns an IQueryable of movies: public IQueryable<Movie> GetMovies() { return new List<Movie> { new Movie {Id=1, Title="Star Wars", Director="Lucas"}, new Movie {Id=2, Title="King Kong", Director="Jackson"}, new Movie {Id=3, Title="Willow", Director="Lucas"}, new Movie {Id=4, Title="Shrek", Director="Smith"}, new Movie {Id=5, Title="Memento", Director="Nolan"} }.AsQueryable(); } If you enter the following URL in your browser: /api/movie?$top=2&$orderby=Title Then you will limit the movies returned to the top 2 in order of the movie Title. You will get the following results: By using the $top option in combination with the $skip option, you can enable client-side paging. For example, you can use $top and $skip to page through thousands of products, 10 products at a time. The $filter query option is very powerful. You can use this option to filter the results from a query. Here are some examples: Return every movie directed by Lucas: /api/movie?$filter=Director eq ‘Lucas’ Return every movie which has a title which starts with ‘S’: /api/movie?$filter=startswith(Title,’S') Return every movie which has an Id greater than 2: /api/movie?$filter=Id gt 2 The complete documentation for the $filter option is located here: http://www.odata.org/developers/protocols/uri-conventions#FilterSystemQueryOption Summary The goal of this blog entry was to provide you with an overview of the new ASP.NET Web API introduced with the Beta release of ASP.NET 4. In this post, I discussed how you can retrieve, insert, update, and delete data by using jQuery with the Web API. I also discussed how you can use the standard validation attributes with the Web API. You learned how to return validation error messages to the client and display the error messages using jQuery. Finally, we briefly discussed how the ASP.NET Web API supports the OData protocol. For example, you learned how to filter records returned from an API controller action by using the $filter query option. I’m excited about the new Web API. This is a feature which I expect to use with almost every ASP.NET application which I build in the future.

    Read the article

  • Introduction to the ASP.NET Web API

    - by Stephen.Walther
    I am a huge fan of Ajax. If you want to create a great experience for the users of your website – regardless of whether you are building an ASP.NET MVC or an ASP.NET Web Forms site — then you need to use Ajax. Otherwise, you are just being cruel to your customers. We use Ajax extensively in several of the ASP.NET applications that my company, Superexpert.com, builds. We expose data from the server as JSON and use jQuery to retrieve and update that data from the browser. One challenge, when building an ASP.NET website, is deciding on which technology to use to expose JSON data from the server. For example, how do you expose a list of products from the server as JSON so you can retrieve the list of products with jQuery? You have a number of options (too many options) including ASMX Web services, WCF Web Services, ASHX Generic Handlers, WCF Data Services, and MVC controller actions. Fortunately, the world has just been simplified. With the release of ASP.NET 4 Beta, Microsoft has introduced a new technology for exposing JSON from the server named the ASP.NET Web API. You can use the ASP.NET Web API with both ASP.NET MVC and ASP.NET Web Forms applications. The goal of this blog post is to provide you with a brief overview of the features of the new ASP.NET Web API. You learn how to use the ASP.NET Web API to retrieve, insert, update, and delete database records with jQuery. We also discuss how you can perform form validation when using the Web API and use OData when using the Web API. Creating an ASP.NET Web API Controller The ASP.NET Web API exposes JSON data through a new type of controller called an API controller. You can add an API controller to an existing ASP.NET MVC 4 project through the standard Add Controller dialog box. Right-click your Controllers folder and select Add, Controller. In the dialog box, name your controller MovieController and select the Empty API controller template: A brand new API controller looks like this: using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Web.Http; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { } } An API controller, unlike a standard MVC controller, derives from the base ApiController class instead of the base Controller class. Using jQuery to Retrieve, Insert, Update, and Delete Data Let’s create an Ajaxified Movie Database application. We’ll retrieve, insert, update, and delete movies using jQuery with the MovieController which we just created. Our Movie model class looks like this: namespace MyWebAPIApp.Models { public class Movie { public int Id { get; set; } public string Title { get; set; } public string Director { get; set; } } } Our application will consist of a single HTML page named Movies.html. We’ll place all of our jQuery code in the Movies.html page. Getting a Single Record with the ASP.NET Web API To support retrieving a single movie from the server, we need to add a Get method to our API controller: using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using MyWebAPIApp.Models; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { public Movie GetMovie(int id) { // Return movie by id if (id == 1) { return new Movie { Id = 1, Title = "Star Wars", Director = "Lucas" }; } // Otherwise, movie was not found throw new HttpResponseException(HttpStatusCode.NotFound); } } } In the code above, the GetMovie() method accepts the Id of a movie. If the Id has the value 1 then the method returns the movie Star Wars. Otherwise, the method throws an exception and returns 404 Not Found HTTP status code. After building your project, you can invoke the MovieController.GetMovie() method by entering the following URL in your web browser address bar: http://localhost:[port]/api/movie/1 (You’ll need to enter the correct randomly generated port). In the URL api/movie/1, the first “api” segment indicates that this is a Web API route. The “movie” segment indicates that the MovieController should be invoked. You do not specify the name of the action. Instead, the HTTP method used to make the request – GET, POST, PUT, DELETE — is used to identify the action to invoke. The ASP.NET Web API uses different routing conventions than normal ASP.NET MVC controllers. When you make an HTTP GET request then any API controller method with a name that starts with “GET” is invoked. So, we could have called our API controller action GetPopcorn() instead of GetMovie() and it would still be invoked by the URL api/movie/1. The default route for the Web API is defined in the Global.asax file and it looks like this: routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); We can invoke our GetMovie() controller action with the jQuery code in the following HTML page: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Get Movie</title> </head> <body> <div> Title: <span id="title"></span> </div> <div> Director: <span id="director"></span> </div> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> getMovie(1, function (movie) { $("#title").html(movie.Title); $("#director").html(movie.Director); }); function getMovie(id, callback) { $.ajax({ url: "/api/Movie", data: { id: id }, type: "GET", contentType: "application/json;charset=utf-8", statusCode: { 200: function (movie) { callback(movie); }, 404: function () { alert("Not Found!"); } } }); } </script> </body> </html> In the code above, the jQuery $.ajax() method is used to invoke the GetMovie() method. Notice that the Ajax call handles two HTTP response codes. When the GetMove() method successfully returns a movie, the method returns a 200 status code. In that case, the details of the movie are displayed in the HTML page. Otherwise, if the movie is not found, the GetMovie() method returns a 404 status code. In that case, the page simply displays an alert box indicating that the movie was not found (hopefully, you would implement something more graceful in an actual application). You can use your browser’s Developer Tools to see what is going on in the background when you open the HTML page (hit F12 in the most recent version of most browsers). For example, you can use the Network tab in Google Chrome to see the Ajax request which invokes the GetMovie() method: Getting a Set of Records with the ASP.NET Web API Let’s modify our Movie API controller so that it returns a collection of movies. The following Movie controller has a new ListMovies() method which returns a (hard-coded) collection of movies: using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using MyWebAPIApp.Models; namespace MyWebAPIApp.Controllers { public class MovieController : ApiController { public IEnumerable<Movie> ListMovies() { return new List<Movie> { new Movie {Id=1, Title="Star Wars", Director="Lucas"}, new Movie {Id=1, Title="King Kong", Director="Jackson"}, new Movie {Id=1, Title="Memento", Director="Nolan"} }; } } } Because we named our action ListMovies(), the default Web API route will never match it. Therefore, we need to add the following custom route to our Global.asax file (at the top of the RegisterRoutes() method): routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); This route enables us to invoke the ListMovies() method with the URL /api/movie/listmovies. Now that we have exposed our collection of movies from the server, we can retrieve and display the list of movies using jQuery in our HTML page: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>List Movies</title> </head> <body> <div id="movies"></div> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> listMovies(function (movies) { var strMovies=""; $.each(movies, function (index, movie) { strMovies += "<div>" + movie.Title + "</div>"; }); $("#movies").html(strMovies); }); function listMovies(callback) { $.ajax({ url: "/api/Movie/ListMovies", data: {}, type: "GET", contentType: "application/json;charset=utf-8", }).then(function(movies){ callback(movies); }); } </script> </body> </html>     Inserting a Record with the ASP.NET Web API Now let’s modify our Movie API controller so it supports creating new records: public HttpResponseMessage<Movie> PostMovie(Movie movieToCreate) { // Add movieToCreate to the database and update primary key movieToCreate.Id = 23; // Build a response that contains the location of the new movie var response = new HttpResponseMessage<Movie>(movieToCreate, HttpStatusCode.Created); var relativePath = "/api/movie/" + movieToCreate.Id; response.Headers.Location = new Uri(Request.RequestUri, relativePath); return response; } The PostMovie() method in the code above accepts a movieToCreate parameter. We don’t actually store the new movie anywhere. In real life, you will want to call a service method to store the new movie in a database. When you create a new resource, such as a new movie, you should return the location of the new resource. In the code above, the URL where the new movie can be retrieved is assigned to the Location header returned in the PostMovie() response. Because the name of our method starts with “Post”, we don’t need to create a custom route. The PostMovie() method can be invoked with the URL /Movie/PostMovie – just as long as the method is invoked within the context of a HTTP POST request. The following HTML page invokes the PostMovie() method. <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Create Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToCreate = { title: "The Hobbit", director: "Jackson" }; createMovie(movieToCreate, function (newMovie) { alert("New movie created with an Id of " + newMovie.Id); }); function createMovie(movieToCreate, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify( movieToCreate ), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { callback(newMovie); } } }); } </script> </body> </html> This page creates a new movie (the Hobbit) by calling the createMovie() method. The page simply displays the Id of the new movie: The HTTP Post operation is performed with the following call to the jQuery $.ajax() method: $.ajax({ url: "/api/Movie", data: JSON.stringify( movieToCreate ), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { callback(newMovie); } } }); Notice that the type of Ajax request is a POST request. This is required to match the PostMovie() method. Notice, furthermore, that the new movie is converted into JSON using JSON.stringify(). The JSON.stringify() method takes a JavaScript object and converts it into a JSON string. Finally, notice that success is represented with a 201 status code. The HttpStatusCode.Created value returned from the PostMovie() method returns a 201 status code. Updating a Record with the ASP.NET Web API Here’s how we can modify the Movie API controller to support updating an existing record. In this case, we need to create a PUT method to handle an HTTP PUT request: public void PutMovie(Movie movieToUpdate) { if (movieToUpdate.Id == 1) { // Update the movie in the database return; } // If you can't find the movie to update throw new HttpResponseException(HttpStatusCode.NotFound); } Unlike our PostMovie() method, the PutMovie() method does not return a result. The action either updates the database or, if the movie cannot be found, returns an HTTP Status code of 404. The following HTML page illustrates how you can invoke the PutMovie() method: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Put Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToUpdate = { id: 1, title: "The Hobbit", director: "Jackson" }; updateMovie(movieToUpdate, function () { alert("Movie updated!"); }); function updateMovie(movieToUpdate, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify(movieToUpdate), type: "PUT", contentType: "application/json;charset=utf-8", statusCode: { 200: function () { callback(); }, 404: function () { alert("Movie not found!"); } } }); } </script> </body> </html> Deleting a Record with the ASP.NET Web API Here’s the code for deleting a movie: public HttpResponseMessage DeleteMovie(int id) { // Delete the movie from the database // Return status code return new HttpResponseMessage(HttpStatusCode.NoContent); } This method simply deletes the movie (well, not really, but pretend that it does) and returns a No Content status code (204). The following page illustrates how you can invoke the DeleteMovie() action: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Delete Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> deleteMovie(1, function () { alert("Movie deleted!"); }); function deleteMovie(id, callback) { $.ajax({ url: "/api/Movie", data: JSON.stringify({id:id}), type: "DELETE", contentType: "application/json;charset=utf-8", statusCode: { 204: function () { callback(); } } }); } </script> </body> </html> Performing Validation How do you perform form validation when using the ASP.NET Web API? Because validation in ASP.NET MVC is driven by the Default Model Binder, and because the Web API uses the Default Model Binder, you get validation for free. Let’s modify our Movie class so it includes some of the standard validation attributes: using System.ComponentModel.DataAnnotations; namespace MyWebAPIApp.Models { public class Movie { public int Id { get; set; } [Required(ErrorMessage="Title is required!")] [StringLength(5, ErrorMessage="Title cannot be more than 5 characters!")] public string Title { get; set; } [Required(ErrorMessage="Director is required!")] public string Director { get; set; } } } In the code above, the Required validation attribute is used to make both the Title and Director properties required. The StringLength attribute is used to require the length of the movie title to be no more than 5 characters. Now let’s modify our PostMovie() action to validate a movie before adding the movie to the database: public HttpResponseMessage PostMovie(Movie movieToCreate) { // Validate movie if (!ModelState.IsValid) { var errors = new JsonArray(); foreach (var prop in ModelState.Values) { if (prop.Errors.Any()) { errors.Add(prop.Errors.First().ErrorMessage); } } return new HttpResponseMessage<JsonValue>(errors, HttpStatusCode.BadRequest); } // Add movieToCreate to the database and update primary key movieToCreate.Id = 23; // Build a response that contains the location of the new movie var response = new HttpResponseMessage<Movie>(movieToCreate, HttpStatusCode.Created); var relativePath = "/api/movie/" + movieToCreate.Id; response.Headers.Location = new Uri(Request.RequestUri, relativePath); return response; } If ModelState.IsValid has the value false then the errors in model state are copied to a new JSON array. Each property – such as the Title and Director property — can have multiple errors. In the code above, only the first error message is copied over. The JSON array is returned with a Bad Request status code (400 status code). The following HTML page illustrates how you can invoke our modified PostMovie() action and display any error messages: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Create Movie</title> </head> <body> <script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript"> var movieToCreate = { title: "The Hobbit", director: "" }; createMovie(movieToCreate, function (newMovie) { alert("New movie created with an Id of " + newMovie.Id); }, function (errors) { var strErrors = ""; $.each(errors, function(index, err) { strErrors += "*" + err + "n"; }); alert(strErrors); } ); function createMovie(movieToCreate, success, fail) { $.ajax({ url: "/api/Movie", data: JSON.stringify(movieToCreate), type: "POST", contentType: "application/json;charset=utf-8", statusCode: { 201: function (newMovie) { success(newMovie); }, 400: function (xhr) { var errors = JSON.parse(xhr.responseText); fail(errors); } } }); } </script> </body> </html> The createMovie() function performs an Ajax request and handles either a 201 or a 400 status code from the response. If a 201 status code is returned then there were no validation errors and the new movie was created. If, on the other hand, a 400 status code is returned then there was a validation error. The validation errors are retrieved from the XmlHttpRequest responseText property. The error messages are displayed in an alert: (Please don’t use JavaScript alert dialogs to display validation errors, I just did it this way out of pure laziness) This validation code in our PostMovie() method is pretty generic. There is nothing specific about this code to the PostMovie() method. In the following video, Jon Galloway demonstrates how to create a global Validation filter which can be used with any API controller action: http://www.asp.net/web-api/overview/web-api-routing-and-actions/video-custom-validation His validation filter looks like this: using System.Json; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace MyWebAPIApp.Filters { public class ValidationActionFilter:ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var modelState = actionContext.ModelState; if (!modelState.IsValid) { dynamic errors = new JsonObject(); foreach (var key in modelState.Keys) { var state = modelState[key]; if (state.Errors.Any()) { errors[key] = state.Errors.First().ErrorMessage; } } actionContext.Response = new HttpResponseMessage<JsonValue>(errors, HttpStatusCode.BadRequest); } } } } And you can register the validation filter in the Application_Start() method in the Global.asax file like this: GlobalConfiguration.Configuration.Filters.Add(new ValidationActionFilter()); After you register the Validation filter, validation error messages are returned from any API controller action method automatically when validation fails. You don’t need to add any special logic to any of your API controller actions to take advantage of the filter. Querying using OData The OData protocol is an open protocol created by Microsoft which enables you to perform queries over the web. The official website for OData is located here: http://odata.org For example, here are some of the query options which you can use with OData: · $orderby – Enables you to retrieve results in a certain order. · $top – Enables you to retrieve a certain number of results. · $skip – Enables you to skip over a certain number of results (use with $top for paging). · $filter – Enables you to filter the results returned. The ASP.NET Web API supports a subset of the OData protocol. You can use all of the query options listed above when interacting with an API controller. The only requirement is that the API controller action returns its data as IQueryable. For example, the following Movie controller has an action named GetMovies() which returns an IQueryable of movies: public IQueryable<Movie> GetMovies() { return new List<Movie> { new Movie {Id=1, Title="Star Wars", Director="Lucas"}, new Movie {Id=2, Title="King Kong", Director="Jackson"}, new Movie {Id=3, Title="Willow", Director="Lucas"}, new Movie {Id=4, Title="Shrek", Director="Smith"}, new Movie {Id=5, Title="Memento", Director="Nolan"} }.AsQueryable(); } If you enter the following URL in your browser: /api/movie?$top=2&$orderby=Title Then you will limit the movies returned to the top 2 in order of the movie Title. You will get the following results: By using the $top option in combination with the $skip option, you can enable client-side paging. For example, you can use $top and $skip to page through thousands of products, 10 products at a time. The $filter query option is very powerful. You can use this option to filter the results from a query. Here are some examples: Return every movie directed by Lucas: /api/movie?$filter=Director eq ‘Lucas’ Return every movie which has a title which starts with ‘S’: /api/movie?$filter=startswith(Title,’S') Return every movie which has an Id greater than 2: /api/movie?$filter=Id gt 2 The complete documentation for the $filter option is located here: http://www.odata.org/developers/protocols/uri-conventions#FilterSystemQueryOption Summary The goal of this blog entry was to provide you with an overview of the new ASP.NET Web API introduced with the Beta release of ASP.NET 4. In this post, I discussed how you can retrieve, insert, update, and delete data by using jQuery with the Web API. I also discussed how you can use the standard validation attributes with the Web API. You learned how to return validation error messages to the client and display the error messages using jQuery. Finally, we briefly discussed how the ASP.NET Web API supports the OData protocol. For example, you learned how to filter records returned from an API controller action by using the $filter query option. I’m excited about the new Web API. This is a feature which I expect to use with almost every ASP.NET application which I build in the future.

    Read the article

  • jQuery Templates, Data Link

    - by Renso
    Normal 0 false false false EN-US X-NONE X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin-top:0in; mso-para-margin-right:0in; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0in; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} Query Templates, Data Link, and Globalization I am sure you must have read Scott Guthrie’s blog post about jQuery support and officially supporting jQuery's templating, data linking and globalization, if not here it is: jQuery Templating Since we are an open source shop and use jQuery and jQuery plugins extensively to say the least, decided to look into the templating a bit and see what data linking is all about. For those not familiar with those terms here is the summary, plenty of material out there on what it is, but here is what in my experience it means: jQuery Templating: A templating engine that allows you to specify a client-side template where you indicate which properties/tags you want dynamically updated. You in a sense specify which parts of the html is dynamic and since it is pluggable you are able to use tools data jQuery data linking and others to let it sync up your template with data. What makes it more powerful is that you can easily work with rows of data, adding and removing rows. Once the template has been generated, which you do dynamically on a client-side event, you then append/inject the resulting template somewhere in your DOM, like for example you would get a JSON object from the database, map it to your template, it populates the template with your data in the indicated places, and then let’s say for example append it to a row in a table. I have not found it that useful for lets say a single record of data since you could easily just get a partial view from the server via an html type ajax call. It really shines when you dynamically add/remove rows from a list in the DOM. I have not found an alternative that meets the functionality of the jQuery template and helps of course that Microsoft officially supports it. In future versions of the jQuery plug-in it may even ship as part of the standard jQuery library and with future versions of Visual Studio. jQuery Data Linking: In short I was fascinated by it initially by how with one line of code I can sync up my JSON object with my form elements. That's where my enthusiasm stopped. It was one-line to let is deal with syncing up your form with your JSON object, but it is not bidirectional as they state and I tried all the work arounds they suggested and none of them work. The problem is that when you update your JSON object it DOES NOT sync it up with your form. In an example, accounts are being edited client side by selecting the account from a list by clicking on the row, it then fetches the entire account JSON object via ajax json-type call and then refreshes the form with the account’s details from the new JSON object. What is the use of syncing up my JSON with the form if I still have to programmatically sync up my new JSON object with each DOM property?! So you may ask: “what is the alternative”? Good question and the same one I was pondering, maybe I can just use it for keeping my from n sync with my JSON object so I can post that JSON object back to the server and update my database. That’s when I discovered Knockout: Knockout It addresses the issues mentioned above and also supports event handling through the observer pattern. Not wanting to go into detail here, Steve Sanderson, the creator of Knockout, has already done a terrific job of that, thanks Steve for a great plug-in! Best of all it integrates perfectly with the jQuery Templating engine as well. I have not found an alternative to this plugin that supports the depth and width of functionality and would recommend it to anyone. The only drawback is the embedded html attributes (data-bind=””) tags that you have to add to the HTML, in my opinion tying your behavior to your HTML, where I like to separate behavior from HTML as well as CSS, so the HTML is purely to define content, not styling or behavior. But there are plusses to this as well and also a nifty work around to this that I will just shortly mention here with an example. Instead of data binding an html tag with knockout event handling like so:  <%=Html.TextBox("PrepayDiscount", String.Empty, new { @class = "number" })%>   Do: <%=Html.DataBoundTextBox("PrepayDiscount", String.Empty, new { @class = "number" })%>   The html extension above then takes care of the internals and you could then swap Knockout for something else if you want to inside the extension and keep the HTML plugin agnostic. Here is what the extension looks like, you can easily build a whole library to support all kinds of data binding options from this:      public static class HtmlExtensions       {         public static MvcHtmlString DataBoundTextBox(this HtmlHelper helper, string name, object value, object htmlAttributes)         {             var dic = new RouteValueDictionary(htmlAttributes);             dic.Add("data-bind", String.Format("value: {0}", name));             return helper.TextBox(name, value, dic);         }       }   Hope this helps in making a decision when and where to consider jQuery templating, data linking and Knockout.

    Read the article

< Previous Page | 168 169 170 171 172 173 174 175 176 177 178 179  | Next Page >