<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Jon Galloway</title><link>http://weblogs.asp.net/jgalloway/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/jongalloway" /><feedburner:info uri="jongalloway" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Tech News</media:category><itunes:explicit>no</itunes:explicit><itunes:subtitle></itunes:subtitle><itunes:category text="Technology"><itunes:category text="Tech News" /></itunes:category><geo:lat>32.761801</geo:lat><geo:long>-117.012737</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/</creativeCommons:license><image><url>http://farm1.static.flickr.com/175/buddyicons/36836555@N00.jpg?1169797019</url><title>Jon Galloway</title></image><feedburner:emailServiceId>jongalloway</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Why I Taught My Daughter To Code (A Little)</title><link>http://feedproxy.google.com/~r/jongalloway/~3/czEBCvaoVBE/why-i-taught-my-daughter-to-code-a-little.aspx</link><pubDate>Wed, 16 May 2012 22:11:37 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8488927</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8488927</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/05/16/why-i-taught-my-daughter-to-code-a-little.aspx#comments</comments><description>&lt;h2&gt;Literacy&lt;/h2&gt;  &lt;p&gt;Imagine a world in which very few people knew how to read or write. You kept to certain parts of town because you couldn't read a map or a street sign. When you needed to sign a contract, you just asked what it said and had to take it on faith. A lot of your experience was based on legend and rumor. Books, and the information in them, were mystical. Sometimes you suspected they were being used against you, but you never really knew.&lt;/p&gt;  &lt;p&gt;There was definitely plenty of work around, but some high end jobs weren't remotely possible - not just clerical work, but professions that required a lot of information management, like the medical and legal professions.&lt;/p&gt;  &lt;h2&gt;Please don't tell me not to learn to code&lt;/h2&gt;  &lt;p&gt;Over this past year, there have been commentary back and forth on whether everyone should learn to code. A few free, interactive sites like &lt;a href="http://www.codecademy.com"&gt;Codecademy&lt;/a&gt; popped up which made it easy to start learning some basic coding. I was a big fan - I helped my eleven year old daughter go through it, and we both agreed it was great. More on that later.&lt;/p&gt;  &lt;p&gt;Then Codecademy launched &lt;a href="http://codeyear.com/"&gt;Code Year&lt;/a&gt; - a grand plan to teach hundreds of thousands of people to code. It was a big hit - even NYC's mayor signed up.&lt;/p&gt;  &lt;p&gt;But no good deed goes unpunished, and there's been some snarky criticism from - you guessed it - professional coders. The latest if Jeff Atwood's post, &lt;a href="http://www.codinghorror.com/blog/2012/05/please-dont-learn-to-code.html"&gt;Please Don't Learn To Code&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Hogwash. &lt;strong&gt;Learning some basic coding is an excellent investment of anyone's time&lt;/strong&gt;.&lt;/p&gt;  &lt;h2&gt;Easy on the Straw Men&lt;/h2&gt;  &lt;p&gt;It's &amp;quot;please don't hear what I'm not saying&amp;quot; time.&lt;/p&gt;  &lt;p&gt;I don't think that the general populace needs to be proficient at writing code. It would be silly to argue Mayor Bloomberg shouldn't be slinging Javascript on the job (as Jeff does). That's not at all the goal. &lt;strong&gt;Nobody's saying that everyone should become a programmer.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;What I - and others - are saying is that learning some basic coding skills is an excellent investment of anyone's time. I'll make two arguments:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Understanding computers (including all the computing devices and products that surround us) is of huge and growing benefit to everyone. &lt;/li&gt;    &lt;li&gt;Basic programming is an excellent way to gain some of that understanding. &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Computer Literacy as a Basic Life Skill - Right Now&lt;/h2&gt;  &lt;p&gt;Right now, pretty much every part of life is in some way affected by computers - most pretty heavily. Shopping, socializing, medicine, education, law, entertainment and more are all at the very least affected by computers and the internet. My three daughters had a use for basic computer skills long before math would do them any good.&lt;/p&gt;  &lt;p&gt;This only gets more intense with increasing age. Teenagers can greatly profit from computer expertise and tech savvy. It's hard to imagine a college program (at least one with any practical application) that didn't involve a hefty amount of computer usage - from basic internet research and word processing on up to simulation and research.&lt;/p&gt;  &lt;p&gt;Most careers (in the industrial world) involve some amount of information management, and workers in these professions who have some computer skill can often be a lot more effective. That includes areas where even a decade ago people might not have expected to see computers - agriculture, construction, family-run restaurants.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;I've talked with countless &amp;quot;civilians&amp;quot; who have profited from computer skills over the years&lt;/strong&gt; - a real estate appraiser who figured out how to automate using Excel and worked circles around his colleagues, film makers and musicians who figured out how to record, market and distribute on the internet, non-techies who sell things online, a school facilities manager who figured out how to cut costs significantly using computer security and automation.&lt;/p&gt;  &lt;p&gt;And many of those people had new doors and careers open to them due to their new-found computer skills. When the real estate market slowed down, the appraiser jumped right into a technology job. Heck, learning to code on my own - starting with my grade school's Apple II - gave me the option to jump into a computer career after I got out of the Navy (in a technical but not computer related field).&lt;/p&gt;  &lt;h2&gt;Computer Literacy as an Absolute Essential in the Very Near Future&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The future is already here — it's just not very evenly distributed.&amp;quot;&lt;/p&gt;    &lt;p&gt;- William Gibson&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It should be obvious to anyone paying attention that computers have become a huge part of our daily lives, and that trend is rapidly accelerating.&lt;/p&gt;  &lt;p&gt;I'm reading &lt;a href="http://www.amazon.com/gp/product/0307473333?ie=UTF8&amp;amp;tag=jongall-20&amp;amp;linkCode=shr&amp;amp;camp=213733&amp;amp;creative=393185&amp;amp;creativeASIN=0307473333&amp;amp;ref_=tmm_pap_title_0&amp;amp;qid=1336467157&amp;amp;sr=8-1"&gt;Physics of the Future&lt;/a&gt; (Michio Kaku). It's a fascinating book in which Michio points to obvious trends and extrapolates where things are going in the near future. In many cases, even a very conservative estimate - or even a look around - shows that every part of life will soon involve interacting with computers and the internet. He points out that global powers during World War II would have killed for the computational power in a simple musical birthday card. Now, we just throw them away. Average mobile phones rival supercomputers from the not-too-distant past, and they're connected to a growing internet and GPS satellites. In the next few decades, computers will continue to shrink and become integrated into everything we interact with.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The quality of our everyday lives will be greatly affected by how we interact with computers. &lt;/strong&gt;&lt;strong&gt;How should that interaction take place?&lt;/strong&gt;&lt;/p&gt;  &lt;h2&gt;Magical! Or, Should We See Computers as Products or Tools?&lt;/h2&gt;  &lt;p&gt;Technology companies work hard to package technology so that it can be used naturally, so consumers won't have to think or fiddle with details. This is a good thing. Anyone working in technology should be focused, consumed with the challenge of exposing &lt;em&gt;the possible&lt;/em&gt; as &lt;em&gt;the natural&lt;/em&gt;. We should be doing this not just because it's a worthy goal, but because it makes good business sense - friendly products sell.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;But it is not in the average consumer's interest for them to blindly buy into this magical experience.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Think about the historical progress in how informed consumers approach medicine. In ancient times, mystics sold magic and consumers had no real insight into what they were buying. Over the centuries, the public has gained a much more informed view of science and medicine, and this is of huge benefit to them as consumers. We expect to see evidence, we read about product recalls, and the market for doctors who sell amulets and snake oils is pretty small. This applies to other areas of life, as well. While I could get around in a car I thought was powered by tiny horses, I'd be unlikely to make wise decisions regarding the purchase and repairs to said car. An informed approach to modern life helps.&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-05-16 15h06_11" href="http://www.flickr.com/photos/36836555@N00/7212015394/"&gt;&lt;img border="0" alt="2012-05-16 15h06_11" src="http://farm8.static.flickr.com/7240/7212015394_78a00ca144.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now think about the consumer approach to computer products. &lt;/p&gt;  &lt;p&gt;Think about how computers and technology are shown in movies and TV. &lt;/p&gt;  &lt;p&gt;Think about how helpless your relatives and neighbors feel when they're buying techy products, or when something doesn't work. &lt;/p&gt;  &lt;p&gt;Think about a friend or relative who paid too much for a website that never worked right.&lt;/p&gt;  &lt;p&gt;Ah, but you may be thinking about a favorite company who sells you magical products right now, or runs some of your favorite websites, or sells you apps or movies. Well marketed brands that have built reputations for quality and ease of use have helped uninformed consumers navigate the technology landscape, but keep in mind that these companies have divided interests. It's their job. They want to sell you things, and their stockholders demand that they bring in as much profit as they can from those sales. &lt;strong&gt;Mindless and uninformed&lt;/strong&gt; brand loyalty is not only expensive, it's by nature counter to your interests. It's no way to live - and thrive - in a digital world.&lt;/p&gt;  &lt;h2&gt;Computer Literacy as a Leadership Requirement&lt;/h2&gt;  &lt;p&gt;The basic level of technical understanding that we expect of our leaders must grow with time in order for them to govern. We expect them to understand our legal system, but we also expect they should know that medicines are chemicals which influence the biological processes in our bodies, that electricity powers lightbulbs and is transmitted over an electrical power grid, that mobile phones have radios in them, etc. &lt;strong&gt;I'd be scared to hear that our leadership didn't have a very basic understanding of our modern world.&lt;/strong&gt; They write and enforce laws and policies that greatly impact our lives, so they need to have a clue about the world we live in.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In the same way, leaders who see computers as magic boxes, coders as wizards, and computer code as incantations can't effectively govern.&lt;/strong&gt; They can't set policy, they can't have informed legal opinions, they have no framework for evaluating whether information being fed to them makes any sense (or even knowing if they should ask). &lt;/p&gt;  &lt;p&gt;Leadership requires understanding, and more, it requires - well, a sense of direction. The future is going to include more and more technology, and leaders who don't understand the present or even have a rough idea of the road ahead are a menace.&lt;/p&gt;  &lt;h2&gt;Computer Literacy as an Educational Oversight&lt;/h2&gt;  &lt;p&gt;I've been describing why non-techies can benefit from some computer literacy. Unfortunately, they won't get it in from our schools.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Computer literacy is undoubtedly of more use to most people than the foreign languages most high schools require&lt;/strong&gt; (I want those 4 years I spent on high school French back). I have rich conversations with people worldwide thanks to the internet and automated translations, not any time I've spent studying languages.&lt;/p&gt;  &lt;p&gt;Though it may offend, &lt;strong&gt;computer skills are of more use to the huge majority than mathematics including and beyond first year algebra.&lt;/strong&gt; Most people will rarely if ever use algebra; everyone uses computers. &lt;/p&gt;  &lt;p&gt;Consider this: in the off chance that the average farmer / dentist / lawyer / car mechanic / stay at home parent / author / teacher / etc. needs to solve an algebra problem, they can &lt;a href="http://www.bing.com/search?q=3x+%2B+7y+%3D+4y+-+35&amp;amp;qs=n&amp;amp;form=QBRE&amp;amp;pq=3x+%2B+7y+%3D+4y+-+35&amp;amp;sc=0-11&amp;amp;sp=-1&amp;amp;sk="&gt;punch it into the search engine and get the answer&lt;/a&gt;: &lt;a href="http://www.wolframalpha.com/input/?i=3x+%2b+7y+%3d+4y+-+35&amp;amp;incTime=true"&gt;3x + 7y = 4y - 35&lt;/a&gt;. Or, more likely, just ask their phone.&lt;/p&gt;  &lt;p&gt;The same goes for so many things we devote educational time to. Does the average high school graduate remember anything important about titration or Augustus or sentence diagram? Titian or Taft? Or even remember how WWI started? Does it matter when they can just look it up on Wikipedia?&lt;/p&gt;  &lt;p&gt;I'm all in favor a balanced education. I got a B.S. Physics (with honors) from Annapolis and went through the US Navy Nuclear Power program (a very rigorous engineering program) following that. My parents were both school teachers. My wife and I homeschool our daughters and put a very high priority on their education. I see education is important, and I think STEM is an important priority. &lt;/p&gt;  &lt;p&gt;But in the broader perspective, our educational priorities are often focused on a historical ideal, completely out of touch with a world in which nearly everyone interacts regularly with computers that most people barely understand.&lt;/p&gt;  &lt;p&gt;This is a much bigger discussion, but here's the main takeaway: after thousands of hours in the classroom, our students emerge unempowered into an increasingly digital world. &lt;strong&gt;We're on our own here.&lt;/strong&gt;&lt;/p&gt;  &lt;h2&gt;Excess Capacity: Oh, the Hours We Throw Away&lt;/h2&gt;  &lt;p&gt;Fine, most people could benefit from some computer literacy. But who has the time?&lt;/p&gt;  &lt;p&gt;I don't buy it. We as a society throw away countless hours on games, entertainment, and apparently even tracking the adventures of someone called Snooki. We make video mashups and silly tumblogs and meme pictures of cats. We catalog &lt;a href="http://en.wikipedia.org/wiki/Pok%C3%A9mon"&gt;Pokémon&lt;/a&gt;. We read books about vampires romancing high school girls. We write long blog posts.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;We have the time.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;We have a ridiculous amount of leisure time, hours we just throw away because we can't think of anything better to do.&lt;/p&gt;  &lt;h2&gt;Basic Coding as a Gateway To Basic Computer Literacy&lt;/h2&gt;  &lt;p&gt;While it might make sense, I'm not proposing citizens spend a mandatory two years in the &amp;quot;Get Smart About Computers&amp;quot; corps. I'm just proposing that: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Non-techies consider spending a few hours learning how computers work. &lt;/li&gt;    &lt;li&gt;Techies encouraging them - and not actively discouraging them! Sheesh! &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Thankfully, getting a basic idea of how computers work has gotten incredibly easy. Sites like &lt;a href="http://www.codecademy.com/"&gt;Codecademy make it easy to learn&lt;/a&gt; - hands on - how computers work. These lessons are hands-on, and they're practical. You learn web fundamentals and how to build a simple website. This is empowering stuff. It's a great way to start the journey from a powerless consumer to a contributor, or at least informed consumer. It's not time consuming, and it's free.&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-05-16 13h21_50" href="http://www.codecademy.com/tracks/"&gt;&lt;img border="0" alt="2012-05-16 13h21_50" src="http://farm6.static.flickr.com/5315/7211495278_f976739f30.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Maybe some of the negative reactions from coders to the Code Year phenomenon have come from not bothering to actually &lt;a href="http://www.codecademy.com/tracks/code-year"&gt;read what's in the classes&lt;/a&gt; and assuming that the goal was to turn a bunch of people into programmers. Maybe.&lt;/p&gt;  &lt;h2&gt;Case Study: Rosemary, Champion of the World (and my daughter)&lt;/h2&gt;  &lt;p&gt;This past year, my daughter asked me if I could teach her computers. I talked to my wife and rolled it into her school plan. We had ten lessons. During this time, we worked did the following:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;We worked through the &lt;a href="http://www.codecademy.com/courses/programming-intro?curriculum_id=4f4b35445cb288000300000c"&gt;Getting Started With Programming section&lt;/a&gt; of the Codecademy Javascript Fundamentals course. She did all the work on her own, and when she got stuck I would have her re-read the instructions out loud. She'd say &amp;quot;Oh! I should have read more carefully!&amp;quot; and move on. She learned some basic loops and conditionals - nothing difficult. I gave her at test on &lt;a href="http://repl.it/"&gt;repl.it&lt;/a&gt; where she wrote a loop from 1 to 25, outputting either &amp;quot;You are too young to drive a car!&amp;quot; or &amp;quot;Your age is 20, you can drive a car!&amp;quot; &lt;/li&gt;    &lt;li&gt;She asked how the internet works, so &lt;a href="http://www.youtube.com/watch?v=qv0XCaUkfNk"&gt;we watched a video on YouTube&lt;/a&gt; about how the internet works. Then we went on a field trip to our router, and we talked about how to &amp;quot;fix the internet&amp;quot; when it's not working. &lt;/li&gt;    &lt;li&gt;She asked about making a web page, and how web pages work. We played with browser tools (Chrome and IE) and she learned the difference between HTML, CSS, and Javascript. I let her recolor my webpage pink, and we went to CNN and put her picture and the headline of her choice in the headlines. &lt;/li&gt;    &lt;li&gt;She asked about making a computer game. We talked about why that would take some work, and planned to do that when we started back up in the semester. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a title="2012-05-16 14h05_30" href="http://www.flickr.com/photos/36836555@N00/7211722630/"&gt;&lt;img border="0" alt="2012-05-16 14h05_30" src="http://farm6.static.flickr.com/5464/7211722630_8b9d246f62_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This was fun. We both had a good time. She asked questions that wouldn't have come up otherwise, and she wouldn't have been interested in otherwise.&lt;/p&gt;  &lt;p&gt;More importantly, after only 8 or so hours, I noticed she saw the world differently. She had ideas about what computers should do. She laughed when computers did silly things on TV. She read error messages and solved problems in an intelligent way. She keeps asking about building a computer game.&lt;/p&gt;  &lt;p&gt;She understands that there's no reason that girls can't have fun with computers, too.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;From a time investment of about 8 hours.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This started with writing some Javascript and HTML. That was critical because it helped her understand how computers work. She learned that they were unthinking and unforgiving in the way they followed her instructions. More importantly, she learned that they would do what she told her if she learned their language (in this case, some basic Javascript).&lt;/p&gt;  &lt;h2&gt;Case Study: The Judge&lt;/h2&gt;  &lt;p&gt;In a funny bit of timing, just last night I read about &lt;a href="https://plus.google.com/110412141990454266397/posts/fk5VXPpiQZR#110412141990454266397/posts/fk5VXPpiQZR"&gt;the judge on the Oracle / Google trial was able to make an informed decision about a Java function&lt;/a&gt; because he'd been -shocker - learning some Java. It was something that would have seemed obvious to most programmers, but was delightfully refreshing &lt;a href="http://www.groklaw.net/article.php?story=20120515120106322"&gt;to hear in a court&lt;/a&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Now here is a later followup where the Judge slams Oracle:      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;Judge: We heard the testimony of Mr. Bloch. I couldn't have told you the first thing about Java before this problem. I have done, and still do, a significant amount of programming in other languages. I've written blocks of code like rangeCheck a hundred times before. I could do it, you could do it. The idea that someone would copy that when they could do it themselves just as fast, it was an accident. There's no way you could say that was speeding them along to the marketplace. You're one of the best lawyers in America, how could you even make that kind of argument?      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;Oracle: I want to come back to rangeCheck.      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;Judge: rangeCheck! All it does is make sure the numbers you're inputting are within a range, and gives them some sort of exceptional treatment. That witness, when he said a high school student could do it...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So here's a judge who's able to make an informed decision about a technology case. What's more shocking is that this is news.&lt;/p&gt;  &lt;h2&gt;Some Objections&lt;/h2&gt;  &lt;h3&gt;Shouldn't everyone learn plumbing, too?&lt;/h3&gt;  &lt;p&gt;Jeff's been having fun equating the &amp;quot;learn to code&amp;quot; movement with &amp;quot;learn plumbing!&amp;quot;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.codinghorror.com/.a/6a0120a85dcdae970b01676680302e970b-800wi" /&gt;&lt;/p&gt;  &lt;p&gt;This is one of those fun arguments that sounds good but falls apart after a moment of thought. What would the return on investment be - both in cost and time - for your average person to learn more about plumbing than working a plunger? How often do they work with plumbing in a way that would benefit from a deeper understanding?&lt;/p&gt;  &lt;p&gt;How often do most people work with computers, smartphones, and internet sites in a way that would benefit from knowing a bit more?&lt;/p&gt;  &lt;h3&gt;Not more code! The world needs less code!&lt;/h3&gt;  &lt;p&gt;This is a bad argument for three reasons:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;This is a coder's argument to other coders. Solving your application's issues is often best solved by thinking, not mindless coding - granted. That has nothing to do with whether it's worthwhile for your average person to learn about how computers work. &lt;/li&gt;    &lt;li&gt;It's - perhaps unintentionally - elitist. We nerds have a huge advantage in dealing with the computers that surround us. Telling the rest of the world that they can't join in, or acting like it's harder than it is, is just wrong. &lt;/li&gt;    &lt;li&gt;It assumes that amateurs won't be writing code anyways. I've seen tons of code over the years written by people who had a problem to solve. They cobbled it together from internet searches. It was inelegant, but it worked in that it solved their problem. There are a lot of populist pseudocoding tools out there - think of &lt;a href="http://ifttt.com/wtf"&gt;ifttt&lt;/a&gt; or the use of countless Wordpress plugins - that let real people solve real problems without having to wait for nerds to get involved. They'll do what they need to do, the question is whether we'll encourage them and help them find the structure. &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;Fine, learn computer literacy, not coding!&lt;/h3&gt;  &lt;p&gt;This is at least something. The problem here is twofold:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;It assumes people know what questions to ask, or how to ask them. As long as they see computers and the internet as mystical boxes full of magic, that's not the case. I'm continually helping people solve problems by prompting them to actually read what a program or web page is telling them (and saying that computers and web pages need to give better messages or not require input is irrelevant).      &lt;br /&gt;      &lt;br /&gt;Without knowing the fundamental differences between how computers and people think, people resort to just yelling louder in their own language.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;It assumes we know what people need to learn. That's only kind of true. Often the approaches I've seen here come down to teaching them how to use a particular product or software package, which is definitely not &amp;quot;teaching a man to fish.&amp;quot; Real problem solving skills in the technology world come down to thinking systematically and rationally about technology, which requires some basic understanding. &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;Where Next?&lt;/h2&gt;  &lt;p&gt;If you don't know how to code, get started. &lt;a href="http://www.codecademy.com/#!/exercises/0"&gt;It's free, fun and easy&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;If you know how to code, encourage others around you when they want to learn. Odds are, someone did that for you a while back.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8488927" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=czEBCvaoVBE:QQouEWlwTkI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=czEBCvaoVBE:QQouEWlwTkI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=czEBCvaoVBE:QQouEWlwTkI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=czEBCvaoVBE:QQouEWlwTkI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=czEBCvaoVBE:QQouEWlwTkI:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=czEBCvaoVBE:QQouEWlwTkI:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=czEBCvaoVBE:QQouEWlwTkI:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/czEBCvaoVBE" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/05/16/why-i-taught-my-daughter-to-code-a-little.aspx</feedburner:origLink></item><item><title>ASP.NET MVC Authentication - Customizing Authentication and Authorization The Right Way</title><link>http://feedproxy.google.com/~r/jongalloway/~3/8AfD1LVsdac/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way.aspx</link><pubDate>Fri, 04 May 2012 20:09:22 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8439619</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8439619</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/05/04/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way.aspx#comments</comments><description>&lt;p&gt;We're continuing the ASP.NET Authentication series (yes, I'm doing a few overlapping series, and yes, it's making me dizzy). The previous post covered &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/04/18/asp-net-mvc-authentication-global-authentication-and-allow-anonymous.aspx"&gt;Global Authentication and Allow Anonymous&lt;/a&gt;. This one continues with a simple tip that can be summed up as follows: keep it simple by extending rather than rewriting.&lt;/p&gt;  &lt;p&gt;I see a lot of questions that involve unnecessary complications, and very often it's due to customizing authentication and authorization. For example, developers see that the AuthorizeAttribute won't work for their case, so they start to write a lot of code - using HttpModules, custom view engines, injecting authentication services and sprinkling authorization service calls throughout their controllers, etc. &lt;/p&gt;  &lt;p&gt;Sometimes that's necessary, but it's rare. Most of the time you can handle things with either a custom membership provider, a subclassed AuthorizeAttribute, or both. &lt;a href="http://blogs.teamb.com/craigstuntz/2009/09/09/38390/"&gt;Craig Stuntz summed this up well in a blog post back in 2009&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;If you are developing a web application which requires authentication or security features not included in the regular ASP.NET membership feature, you might decide to implement these features yourself. But it seems as if the first instinct of many ASP.NET MVC developers is to do this by customizing their Controllers, because they’ve decided that &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx"&gt;AuthorizeAttribute&lt;/a&gt; can’t possibly serve their needs. They will decide that the way to do this is to write some sort of parent Controller type which examines the currently logged-in user when an action executes and changes the result of the action based on who they are. Others will try to re-implement AuthorizeAttribute without ever examining the source code for the original.&lt;/p&gt;    &lt;p&gt;These are very bad approaches, for two important reasons:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;&lt;strong&gt;They don’t work.&lt;/strong&gt; If your action result is cached by ASP.NET, then &lt;em&gt;the action will not even run &lt;/em&gt;the next time it is requested. AuthorizeAttribute handles this correctly. Code you write in a Controller &lt;em&gt;cannot &lt;/em&gt;handle this. Code you write in a custom action filter &lt;em&gt;could&lt;/em&gt; work, if you cut and paste the implementation from AuthorizeAttribute. But AuthorizeAttribute is unsealed, so why cut and paste, when you can subtype? &lt;/li&gt;      &lt;li&gt;The modularity is wrong. You should aim to develop MVC sites which can be used with any authentication (or role) provider, whether it is ASP.NET membership, domain authentication, OpenId, or a custom membership provider. Wiring authentication concerns into a Controller makes this extremely difficult. &lt;/li&gt;   &lt;/ol&gt; &lt;/blockquote&gt;  &lt;p&gt;Craig recommends the same thing I'll be recommending - leverage the existing security systems in ASP.NET and ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;ASP.NET MVC's authorization system runs directly on top of the existing ASP.NET security system, and both have well established and tested extensibility points.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;If you need to &lt;strong&gt;customize the way ASP.NET MVC integrates with the underlying ASP.NET security system&lt;/strong&gt;, subclass the AuthorizeAttribute &lt;/li&gt;    &lt;li&gt;If you need to &lt;strong&gt;customize the way the underlying ASP.NET membership system works&lt;/strong&gt;, leverage the existing ASP.NET security provider system &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I'll throw in one more - make sure you really need to customize anything at all.&lt;/p&gt;  &lt;h2&gt;Step Zero: Do you need to customize anything?&lt;/h2&gt;  &lt;p&gt;I've seen some examples that use the techniques below to implement authorization features... which didn't need implementing because they were already built in. AuthorizeAttribute, for example, already includes support for role-based authorization, but I've seen sample code that &amp;quot;adds in&amp;quot; role checking. &lt;/p&gt;  &lt;p&gt;I've also seen examples which were built because the author assumed that AuthorizeAttribute only worked with Forms Authentication. That's not true - it just verifies if the user (1) is authenticated (2) is in the listed users and/or roles (if any are set). The same AuthorizeAttribute works with other authentication methods - the same attribute is also used with Windows Forms in the Intranet Application template, as well.&lt;/p&gt;  &lt;p&gt;The AuthorizeAttribute has a pretty narrowly defined job, so it doesn't take much work to verify whether it already does what you need - &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.108).aspx"&gt;check first&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;Quick Note: Authentication and Authorization&lt;/h2&gt;  &lt;p&gt;Any sufficiently long article on web security must eventually devolve into distinguishing between authentication and authorization, so here goes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Authentication is the act of establishing who the user is. &lt;/li&gt;    &lt;li&gt;Authorization is the act of determining if that user should have access to a resource. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;A user may be authenticated but not authorized to access a resource - e.g. a simple user isn't authorized to access site administration pages. A user may be authorized, but not authenticated - e.g. a site which allows anonymous access, a site which controls access using an API / access key, etc.&lt;/p&gt;  &lt;h2&gt;Customizing ASP.NET MVC's Interaction with ASP.NET Authorization by subclassing AuthorizeAttribute&lt;/h2&gt;  &lt;p&gt;Subclassing an AuthorizeAttribute is pretty straightforward. In most cases you just create a class that inherits form AuthorizeAttribute and override AuthorizeCore. Here's a very simple example: a key based login.&lt;/p&gt;  &lt;h3&gt;A simple key based AuthorizeAttribute&lt;/h3&gt;  &lt;p&gt;In this example, we'll be setting up a custom authorization scheme based on a key which will be validated using a very simple algorithm. This isn't secure for any number of reasons, but with some minor modifications (e.g. expiring a key once it is used) it would be sufficient for things like simple beta program for a pre-release website.&lt;/p&gt;  &lt;p&gt;We'll accept a parameter called X-Key and validate that it's a number that passes a simple check.&lt;/p&gt;  &lt;p&gt;To start with, we'll create a new class called KeyAuthorizeAttribute that inherits from AuthorizeAttribute:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public class KeyAuthorizeAttribute : AuthorizeAttribute  
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string key = httpContext.Request[&amp;quot;X-Key&amp;quot;];
        return ApiValidatorService.IsValid(key);
    }
}

public static class ApiValidatorService
{
    public static bool IsValid(string key)
    {
        int keyvalue;

        if (int.TryParse(key, out keyvalue))
        {
            return keyvalue % 2137 == 7;
        }
        return false;
    }
}&lt;/pre&gt;

&lt;p&gt;This AuthorizeCore method checks a value (via header, querystring, form post, etc.) and calls into a service to validate it. In this case, validation is a simple static method that runs our validation algorithm. In your case, you'd probably want to check against a list of pre-issued keys in a database, call out to an external service, etc. AuthorizeCore returns a boolean value - pass or fail.&lt;/p&gt;

&lt;p&gt;We can then slap that [KeyAuthorize] attribute on any action or controller in the site, or register it globally (as shown in my previous post).&lt;/p&gt;

&lt;p&gt;This request would be allowed: http://localhost:8515/?X-Key=26381272 (because 26381272 mod 2137 equals 7)&lt;/p&gt;

&lt;p&gt;This request would be denied: http://localhost:8515/?X-Key=12345&lt;/p&gt;

&lt;h3&gt;Handling Authorization Failures&lt;/h3&gt;

&lt;p&gt;AuthorizeAttribute is based on Forms Authentication, so when a request fails a call to the AuthorizeCore method of an applicable AuthorizeAttribute, it will by default redirect to the login page so that, hopefully, the user can get authorized. I &lt;a href="http://weblogs.asp.net/jgalloway/archive/2011/04/28/looking-at-how-asp-net-mvc-authorize-interacts-with-asp-net-forms-authorization.aspx"&gt;walked through the mechanics of this redirection process in a previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The default login page doesn't make any sense in a lot of scenarios, including the example above. If someone comes to my site with a missing or incorrect API key, the login page isn't going to help them. For that specific case, I'd perhaps want to redirect them to a page that tells them how to apply for an access key.&lt;/p&gt;

&lt;p&gt;If you need to change what happens when users fail authentication, you've got a few options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If you want to change the site-wide redirection URL for when a request fails authorization, you can change the authentication/forms/loginUrl setting in web.config. Keep in mind, though, that this affects all authentication redirects for your entire application. &lt;/li&gt;

  &lt;li&gt;If you want to run custom logic - including but not limited to redirecting to a URL - you can override the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.handleunauthorizedrequest.aspx"&gt;AuthorizeAttribute's HandleUnauthorizedRequest method&lt;/a&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Many more examples&lt;/h3&gt;

&lt;p&gt;This is a very simple example. You can find a lot more by searching on the override code above, e.g. &amp;quot;override authorizecore httpcontextbase&amp;quot;. Some examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://singulartechnologies.com/custom-asp-net-mvc-authorization-with-facebook-connect"&gt;Custom ASP.NET MVC Authorization with Facebook Connect&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://stackoverflow.com/a/5633161/5"&gt;ASP.NET MVC Forms authentication against an external web service&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://farm-fresh-code.blogspot.com/2011/03/revisiting-custom-authorization-in.html"&gt;Custom authorization to restrict editing based on the owner for a resource&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.aaronstannard.com/post/2011/03/26/How-to-Create-a-Twitter-Anywhere-ActionFilter-in-ASPNET-MVC.aspx"&gt;Twitter @Anywhere Authorization&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://stackoverflow.com/questions/5224324/asp-net-mvc-authentication-based-on-route-params"&gt;ASP.NET MVC Authentication based on Route Params&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://cacheandquery.com/blog/2011/03/customizing-asp-net-mvc-basic-authentication/"&gt;Customizing ASP.NET MVC Basic Authentication&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ff359105(v=PandP.10).aspx"&gt;Federated Identity with Multiple Partners&lt;/a&gt;&amp;#160; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: The last one on the list implements the base AuthorizeAttribute interfaces rather than subclassing AuthorizeAttribute, which bears some discussion.&lt;/p&gt;

&lt;h3&gt;Subclass AuthorizeAttribute or Implement FilterAttribute, IAuthorizationFilter?&lt;/h3&gt;

&lt;p&gt;If you just look at the AuthorizeCore code in the AuthorizeAttribute, you may think it's so trivial you might as well just build your own IAuthorizationFilter from scratch. The problem with that idea is that it's very easy to do that incorrectly. A large amount of the code in the AuthorizeAttribute is there to make sure it works correctly with caching. If you get this wrong, you can very easily open yourself up to this scenario:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Authorized user accesses an action and is correctly granted access. &lt;/li&gt;

  &lt;li&gt;The action uses output caching, so the output is cached for future views. &lt;/li&gt;

  &lt;li&gt;Unauthorized user accesses the action. Since it was cached, the restricted (or user-specific) content is served to the unauthorized user. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AuthorizeAttribute has ensured that the code in the CacheValidateHandler and OnCacheAuthorization methods interact correctly with ASP.NET's caching system. Unless you really know what you're doing, it's a much better idea to start by subclassing AuthorizeAttribute. &lt;/p&gt;

&lt;h3&gt;Using AuthorizeAttribute with ASP.NET Web API&lt;/h3&gt;

&lt;p&gt;ASP.NET Web API uses the same AuthorizeAttribute scheme. It works the same way - drop an attribute on actions, API controllers, or globally, and you're set. All good so far.&lt;/p&gt;

&lt;p&gt;But, if you use System.Web.Mvc.AuthorizeAttribute (or a subclassed attribute) on an Action Controller, nothing will happen. ASP.NET Web API uses a very similar, but different AuthorizeAttribute, found in the System.Web.Http namespace. There are some important differences (beyond the scope of this post), but a good place to look is at how the two AuthorizeAttributes handle unauthorized requests:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/0f8c45fe03e7#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs"&gt;System.Web.Mvc.AuthorizeAttribute.HandleUnauthorizedRequest()&lt;/a&gt; sets the response to an HttpUnauthorizedResult &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/0f8c45fe03e7#src%2fSystem.Web.Http%2fAuthorizeAttribute.cs"&gt;System.Web.Http.AuthorizeAttribute.HandleUnauthorizedRequest()&lt;/a&gt; sets the response to an HttpResponseMessage(HttpStatusCode.Unauthorized) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reflects the difference between the target focus of both systems - ASP.NET MVC primarily focuses on HTML code that's viewed by people in a browser, and ASP.NET Web API primarily focuses on HTTP traffic that's handled by code. In ASP.NET Web API, you don't tell someone they're not authorized with a login page, you return the appropriate HTTP status code.&lt;/p&gt;

&lt;h3&gt;Fluent Security&lt;/h3&gt;

&lt;p&gt;If you have complex authorization requirements - particularly around configuration - you might want to look at &lt;a href="http://www.fluentsecurity.net/getting-started"&gt;Fluent Security&lt;/a&gt;. It provides a fluent, code-based configuration system, which lets you do define your application's authentication requirements in one place, like this:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;SecurityConfigurator.Configure(configuration =&amp;gt;
{
    // Let Fluent Security know how to get the authentication status of the current user
    configuration.GetAuthenticationStatusFrom(() =&amp;gt; HttpContext.Current.User.Identity.IsAuthenticated);

    // Let Fluent Security know how to get the roles for the current user
    configuration.GetRolesFrom(() =&amp;gt; MySecurityHelper.GetCurrentUserRoles());

    // This is where you set up the policies you want Fluent Security to enforce
    configuration.For&amp;lt;HomeController&amp;gt;().Ignore();

    configuration.For&amp;lt;AccountController&amp;gt;().DenyAuthenticatedAccess();
    configuration.For&amp;lt;AccountController&amp;gt;(x =&amp;gt; x.ChangePassword()).DenyAnonymousAccess();
    configuration.For&amp;lt;AccountController&amp;gt;(x =&amp;gt; x.LogOff()).DenyAnonymousAccess();

    configuration.For&amp;lt;BlogController&amp;gt;(x =&amp;gt; x.Index()).Ignore();
    configuration.For&amp;lt;BlogController&amp;gt;(x =&amp;gt; x.AddPost()).RequireRole(BlogRole.Writer);
    configuration.For&amp;lt;BlogController&amp;gt;(x =&amp;gt; x.AddComment()).DenyAnonymousAccess();
    configuration.For&amp;lt;BlogController&amp;gt;(x =&amp;gt; x.DeleteComments()).RequireRole(BlogRole.Writer);
    configuration.For&amp;lt;BlogController&amp;gt;(x =&amp;gt; x.PublishPosts()).RequireRole(BlogRole.Owner);
});

GlobalFilters.Filters.Add(new HandleSecurityAttribute(), 0);&lt;/pre&gt;

&lt;h2&gt;Customizing ASP.NET MVC Authorization using the existing ASP.NET Security systems&lt;/h2&gt;

&lt;p&gt;ASP.NET has been around for a long time. It's been beaten on pretty hard, and the existing systems have undergone a huge amount of real-world testing. When you run into a constraint that pushes you towards writing some custom code, the best approach is to make sure you understand how the existing systems work and integrate with them as closely as possible.&lt;/p&gt;

&lt;p&gt;Since ASP.NET has been around for a long time, there is a good amount of existing information on the security system. It's a big topic. I'm just going to (try to) summarize, pointing out the best extension points from an ASP.NET MVC point of view.&lt;/p&gt;

&lt;h3&gt;Extending the Forms Authentication provider&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, &lt;strong&gt;authentication is the process of establishing who the user is&lt;/strong&gt;. &lt;strong&gt;It doesn't say anything about what access you've got, it just verifies that you are who you claim to be.&lt;/strong&gt; ASP.NET has some built in systems to handle that - the &lt;a href="http://msdn.microsoft.com/en-us/library/7t6b43z4.aspx"&gt;Forms Authentication provider&lt;/a&gt; handles browser based login and account management, and there's a &lt;a href="http://msdn.microsoft.com/en-us/library/907hb5w9.aspx"&gt;Windows Authentication provider&lt;/a&gt; which integrates with the Windows authentication. If you need to modify how authentication works, you'll almost certainly be working with the Forms Authentication provider.&lt;/p&gt;

&lt;p&gt;You might assume that you extend authentication by plugging in a new Authentication Provider, but that's not the case. There are two in the box Authentication Providers, and you can't add new ones. That's pretty much never an issue, though, because the Forms Authentication provider gives you plenty of hooks for extension.&lt;/p&gt;

&lt;p&gt;Warning: The next paragraph is exceptionally nerdy, but it sets some important background for interfacing with Forms Authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://support.microsoft.com/kb/910443"&gt;Forms Authentication uses a Forms Authentication Ticket to track your identity&lt;/a&gt; - essentially your authenticated username. The ticket is stored in an encrypted Forms Authentication Cookie.&amp;#160; There's support for cookieless authentication, which automatically appends cookie information via an encrypted querystring value. There are two main components that make Forms Authentication work - the FormsAuthetication class which sets the authentication cookie for authenticated users, and a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationmodule.aspx"&gt;FormsAuthenticationModule&lt;/a&gt; which checks for the cookie, authenticates you and sets your identity in the HttpContext. Since FormsAuthenticationModule is an HTTP module, &lt;a href="http://msdn.microsoft.com/en-us/library/bb470252.aspx"&gt;it runs for every request, way at the beginning of the pipeline&lt;/a&gt;. That's an important part - a secure authentication system needs to check authentication at the beginning of the request.&lt;/p&gt;

&lt;p&gt;This is all underlying machinery - the important part is that when someone logs in, something in your application calls &lt;a href="http://msdn.microsoft.com/en-us/library/twk5762b.aspx"&gt;FormsAuthentication.SetAuthCookie()&lt;/a&gt;. That sets the Authentication Cookie, which is then checked by the FormsAuthenticationModule on each request. You can see an example of how the default ASP.NET MVC AccountController Login method uses it:&lt;/p&gt;

&lt;pre class="brush: csharp; highlight: [9];"&gt;[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction(&amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;);
            }
        }
        else
        {
            ModelState.AddModelError(&amp;quot;&amp;quot;, &amp;quot;The user name or password provided is incorrect.&amp;quot;);
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}&lt;/pre&gt;

&lt;p&gt;A good example is &lt;a href="https://github.com/AArnott/dotnetopenid"&gt;DotNetOpenAuth&lt;/a&gt;, which adds OpenID, OAuth, and InfoCard authentication to ASP.NET by integrating with the ASP.NET Forms Authentication ticket. You can see how this works in the DotNetOpenAuth &lt;a href="https://github.com/AArnott/dotnetopenid/blob/master/src/DotNetOpenAuth.AspNet/OpenAuthAuthenticationTicketHelper.cs"&gt;OpenAuthAuthenticationTicketHelper.cs class&lt;/a&gt;, and in the &lt;a href="https://github.com/AArnott/dotnetopenid/blob/master/samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs"&gt;OpenIdRelyingPartyMvc sample's UserController&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The important points here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;While it's tempting to look at your custom authentication needs as completely unique, most can be handled by determining who a user is (your code) and then telling ASP.NET Forms Authentication to track them. &lt;/li&gt;

  &lt;li&gt;If you decide that you'd rather just handle authentication outside of ASP.NET, you've got a lot to think about. You'll be writing a lot of new code which hasn't gone through near the security testing, beating, improvements, etc., that Forms Authentication has. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;The ASP.NET Roles and Membership System&lt;/h3&gt;

&lt;p&gt;The above authentication discussion was completely independent of where and how the actual user information was stored, and that's important. Forms Authentication doesn't handle passwords, logins, user roles, etc., it just tracks users once it's been told about them.&lt;/p&gt;

&lt;h4&gt;ASP.NET Membership&lt;/h4&gt;

&lt;p&gt;The default system for managing user and is &lt;a href="http://msdn.microsoft.com/en-us/library/tw292whz.aspx"&gt;ASP.NET Membership&lt;/a&gt;. There's a SqlMembershipProvider that runs against a SQL Server database, but the provider system allows you to plug in your own custom &lt;a href="http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx"&gt;Membership Provider&lt;/a&gt; for managing users. Your login process can use your membership provider to validate the user's credentials, and you can use the membership system to store user information if you want. More on that in a bit.&lt;/p&gt;

&lt;h4&gt;ASP.NET Role Management&lt;/h4&gt;

&lt;p&gt;For some sites, authorization and authentication are nearly synonymous - the only goal of authorization is to prevent anonymous access. But for many sites, you've got different roles - users, administrators, superadministrators, and omegasupremeadministrators. For those cases, you need something that maps users to roles, and that's what &lt;a href="http://msdn.microsoft.com/en-us/library/6b241xwt.aspx"&gt;Role Management Providers&lt;/a&gt; do. In most cases, roles and membership are managed together - the same system that tracks who your users are controls what rights they have. You'll often see role and membership providers in one big package, but they're two separate things.&lt;/p&gt;

&lt;h3&gt;Customizing Membership in ASP.NET&lt;/h3&gt;

&lt;p&gt;As before, the zeroth rule of customizing membership is to reconsider if you need to. There are plenty of hooks into the existing flow, such as overriding &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.onauthorization.aspx"&gt;OnAuthorization&lt;/a&gt; and just &lt;a href="http://bradwilson.typepad.com/blog/2010/07/aspnet-mvc-filters-and-statefulness.html"&gt;adding some information to HttpContext.Items, Session, etc&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you really do need a custom user management system, the first thing to do is look to see if someone's already written it. There are membership providers for a lot of backing systems. A quick search shows tons of them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href="http://nuget.org/packages/System.Web.Providers"&gt;Universal Providers (System.Web.Providers)&lt;/a&gt; work with all editions of SQL Server 2005 and later as well as SQL Azure. Scott Hanselman covered them in detail: &lt;a href="http://www.hanselman.com/blog/IntroducingSystemWebProvidersASPNETUniversalProvidersForSessionMembershipRolesAndUserProfileOnSQLCompactAndSQLAzure.aspx"&gt;Introducing System.Web.Providers - ASP.NET Universal Providers for Session, Membership, Roles and User Profile on SQL Compact and SQL Azure&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.danharman.net/2011/06/23/asp-net-mvc-3-custom-membership-provider-with-repository-injection/"&gt;ASP.Net MVC 3 Custom Membership Provider with Repository Injection&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://mongomembership.codeplex.com/"&gt;MongoDB Membership&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.vikrampant.com/amazon-simpledb-asp-net-membership-provider/"&gt;Amazon SimpleDB Membership&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="https://github.com/martijnboland/RavenDBMembership"&gt;RavenDB Membership&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;Piles of &lt;a href="https://github.com/search?langOverride=&amp;amp;q=%22membership+provider%22&amp;amp;repo=&amp;amp;start_value=1&amp;amp;type=Repositories&amp;amp;utf8=%E2%9C%93"&gt;Membership Providers on GitHub&lt;/a&gt; and &lt;a href="http://www.codeplex.com/site/search?query=membership%20provider&amp;amp;sortBy=CurrentReleaseDate&amp;amp;tagName=%2cMembershipProvider%2c&amp;amp;licenses=|&amp;amp;refinedSearch=true"&gt;CodePlex&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Implementing your own Membership Provider&lt;/h3&gt;

&lt;p&gt;If you don't find a Membership Provider that works for you, it's not difficult to write your own. Remember that you're taking more responsibility for your system's security. Matt Wrock wrote a great overview: &lt;a href="http://www.mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx"&gt;Implementing custom Membership Provider and Role Provider for Authenticating ASP.NET MVC Applications&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's plenty of information on MSDN as well, for example: &lt;a href="http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx"&gt;Implementing a Membership Provider&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Simple Membership&lt;/h3&gt;

&lt;p&gt;You'll notice that a lot of Matt's overview of creating Membership and Role Providers included a lot of System.NotImplementedException, because the ASP.NET Membership Provider system shows some underlying assumptions around user data going in relational databases. You can just ignore those parts and use what you want, but if you find the whole thing a little too complex and are tempted to throw it all out, I'd recommend looking at &lt;a href="http://msdn.microsoft.com/en-us/library/webmatrix.webdata.simplemembershipprovider(v=vs.99).aspx"&gt;SimpleMembership from ASP.NET Web Pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx"&gt;Matthew Osborn wrote an overview of what SimpleMembership is&lt;/a&gt; and how it works in ASP.NET Web Pages. Although it was originally written for ASP.NET Web Pages, it can be readily adapted to ASP.NET MVC using the &lt;a href="http://nuget.org/packages/simplemembership.mvc3"&gt;SimpleMembership.Mvc&lt;/a&gt; NuGet package.&lt;/p&gt;

&lt;h2&gt;Wrapping Up&lt;/h2&gt;

&lt;p&gt;ASP.NET MVC gives you a huge amount of flexibility, and it's tempting to want to write a lot of custom code. If you understand the underlying security systems that ASP.NET MVC uses, though, you can usually integrate with what's in place. You'll be saving yourself a lot of unnecessary code, along with the added costs of testing, debugging and maintenance. More important, though, you'll be using a system that's undergone a huge amount of security testing over the past decade.&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;h4&gt;For further study:&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.codeproject.com/KB/web-security/ASPNET-MVC-Security.aspx"&gt;Implement secure ASP.NET MVC applications&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://odetocode.com/articles/427.aspx"&gt;Membership and Role Providers in ASP.NET 2.0&lt;/a&gt; (!) from K. Scott Allen &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.codeproject.com/Articles/165159/Custom-Membership-Providers"&gt;Custom Membership Providers&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8439619" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=8AfD1LVsdac:PoNogXqH2wg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=8AfD1LVsdac:PoNogXqH2wg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=8AfD1LVsdac:PoNogXqH2wg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=8AfD1LVsdac:PoNogXqH2wg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=8AfD1LVsdac:PoNogXqH2wg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=8AfD1LVsdac:PoNogXqH2wg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=8AfD1LVsdac:PoNogXqH2wg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/8AfD1LVsdac" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/05/04/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way.aspx</feedburner:origLink></item><item><title>Upcoming Web Camps</title><link>http://feedproxy.google.com/~r/jongalloway/~3/HtJVNs4Dl-M/upcoming-web-camps.aspx</link><pubDate>Tue, 01 May 2012 02:57:29 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8424721</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8424721</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/04/30/upcoming-web-camps.aspx#comments</comments><description>&lt;p&gt;&lt;img src="http://files.channel9.msdn.com/thumbnail/1265194e-62fc-4ea0-baa8-f0462f303ee0.png" /&gt;&lt;/p&gt;  &lt;p&gt;We've got some great, free &lt;a href="http://www.devcamps.ms/web"&gt;Web Camps&lt;/a&gt; headed your way!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Web Camps are free, fun, no-fluff events for developers, by developers.&lt;/strong&gt; Show up for the day, leave infused with a crazy amount of web dev info. Did I mention these are free?&lt;/p&gt;  &lt;p&gt;My teammate &lt;a href="http://www.bradygaster.com/"&gt;Brady Gaster&lt;/a&gt; has put together some phenomenal new content, and I'm really looking forward to presenting at some of these. &lt;/p&gt;  &lt;h2&gt;Web Camps Locations&lt;/h2&gt;  &lt;p&gt;So far the following locations have been announced:&lt;/p&gt; &lt;style&gt;



table.minimal { border-collapse: collapse; }
table.minimal th, table.minimal td { border: 1px solid black; }&lt;/style&gt;  &lt;table class="minimal" width="100%"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;th&gt;Location&lt;/th&gt;        &lt;th&gt;Date&lt;/th&gt;        &lt;th&gt;Registration&lt;/th&gt;        &lt;th&gt;Notes&lt;/th&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Brussels, Belgium&lt;/td&gt;        &lt;td&gt;3-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032510653&amp;amp;Culture=en-US"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;With &lt;a href="http://www.bradygaster.com"&gt;Brady Gaster&lt;/a&gt; and &lt;a href="http://blog.osbornm.com/"&gt;Matthew Osborn&lt;/a&gt;... and there's still room!&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Waltham, MA&lt;/td&gt;        &lt;td&gt;10-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032510540&amp;amp;culture=en-us"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;I'll be here!&lt;/strong&gt; Also starring &lt;a href="http://blogs.msdn.com/b/cbowen/"&gt;Chris Bowen&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/b/jimoneil/"&gt;Jim O'Neil&lt;/a&gt;!&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Mountain View, CA&lt;/td&gt;        &lt;td&gt;14-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032506730&amp;amp;culture=en-us"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;With the amazing &lt;a href="http://blogs.msdn.com/b/dorischen/"&gt;Doris Chen&lt;/a&gt;!&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Denver, CO&lt;/td&gt;        &lt;td&gt;18-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032506737&amp;amp;culture=en-us"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;Also Doris Chen!&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Phoenix, AZ&lt;/td&gt;        &lt;td&gt;25-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032506738&amp;amp;culture=en-us"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;Also Doris Chen! Wow, she's busy!&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;Mountain View, CA&lt;/td&gt;        &lt;td&gt;29-May-12&lt;/td&gt;        &lt;td&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032512981&amp;amp;Culture=en-US"&gt;Register Here&lt;/a&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;I'll be here!&lt;/strong&gt; Maybe someone else, too.&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;There are a bunch more that are in the works but not quite ready to be announced yet - I'll update here, but the best place to keep up to date is at &lt;a title="http://www.devcamps.ms/web" href="http://www.devcamps.ms/web"&gt;http://www.devcamps.ms/web&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Oh, and I believe there's still room at the Web Camp in &lt;strong&gt;Brussels on May 3&lt;/strong&gt;.&lt;/p&gt;  &lt;h2&gt;Web Camps Content&lt;/h2&gt;  &lt;p&gt;I've reviewed and contributed a bit to the Web Camps content that Brady's put together, and it's really, really good. There's a ton of information packed in. Here's an overview of the agenda (see the registration link for the exact agenda at each location):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Welcome Back to the Microsoft Web Stack &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Integrating Your Site with Internet Explorer 9 &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Top 10 Things You Didn't Know about WebMatrix 2 &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Creating Rich HTML 5 Experiences &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Building Web Sites Using ASP.NET 4.5 &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Building a Service Layer with ASP.NET Web API &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Deploying ASP.NET Apps to the Cloud&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You can read more about those topic at &lt;a title="http://www.devcamps.ms/web/agenda" href="http://www.devcamps.ms/web/agenda"&gt;http://www.devcamps.ms/web/agenda&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;Infomercial!&lt;/h2&gt;  &lt;p&gt;Now if you're almost convinced, but on the edge, and you need a video to push you over the top, you watch &lt;a href="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012"&gt;Brady and me announcing the Web Camps tour on Web Camps TV&lt;/a&gt; a few weeks ago:&lt;/p&gt; &lt;iframe style="width: 512px; height: 288px" src="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012/player?w=512&amp;amp;h=288" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;  &lt;p&gt;Yes, if you read my blog you'll have noticed that this video is a repeat. That's how infomercials work.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8424721" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=HtJVNs4Dl-M:lJHisoFqWE4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=HtJVNs4Dl-M:lJHisoFqWE4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=HtJVNs4Dl-M:lJHisoFqWE4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=HtJVNs4Dl-M:lJHisoFqWE4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=HtJVNs4Dl-M:lJHisoFqWE4:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=HtJVNs4Dl-M:lJHisoFqWE4:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=HtJVNs4Dl-M:lJHisoFqWE4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/HtJVNs4Dl-M" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET/default.aspx">ASP.NET</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/04/30/upcoming-web-camps.aspx</feedburner:origLink></item><item><title>Windows 8 and ASP.NET Web API - Part 1 - Getting Started</title><link>http://feedproxy.google.com/~r/jongalloway/~3/vnJ5fWXiI4E/windows-8-and-asp-net-web-api-part-1-getting-started.aspx</link><pubDate>Fri, 27 Apr 2012 12:26:26 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8413902</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>7</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8413902</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/04/27/windows-8-and-asp-net-web-api-part-1-getting-started.aspx#comments</comments><description>&lt;p&gt;Many of the key Windows 8 Metro Style application features either require or can greatly benefit from a connection to online services. ASP.NET Web API is a great fit for these services, as it's tightly focused around providing HTTP services to applications. I'm starting a series that will look at how to leverage ASP.NET Web API services from Windows 8 applications.&lt;/p&gt;  &lt;p&gt;In this first post in the series, we'll begin with a simple C# Windows 8 Metro Style application that displays data from the ASP.NET Web API Contact Manager sample. Once we've got the basics locked down, we'll move on to some more complex topics. I'm thinking Live Tiles and Notifications, but I'm interested in your ideas of where to go next, so please let me know in the comments.&lt;/p&gt;  &lt;h2&gt;The ASP.NET Web API Contact Manager sample&lt;/h2&gt;  &lt;p&gt;I thought it would be simplest to start with an official, tried and true Web API sample that's been around since the early days of WCF Web API - the Contact Manager Sample. You can download the code here: &lt;a title="http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d" href="http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d"&gt;http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This code is originally written for Visual Studio 2010, but I'm going to be working on Visual Studio 11 Beta running on Windows 8 Consumer Preview, so I ran through the upgrade. There's an alert which says &amp;quot;One or more Web Application projects in this solution require SQL Server Express. You will need to download and install the appropriate version of SQL Server Express for these projects to work.&amp;quot; A quick look at the code, however shows that all the data is in-memory, so we can ignore it. If we keep with this code for long, we can just remove the offending NuGet package, but let's not let that slow us down just yet.&lt;/p&gt;  &lt;p&gt;Running the application shows that the application is indeed working. &lt;/p&gt;  &lt;p&gt;&lt;a title="2012-04-27_01h26_16" href="http://www.flickr.com/photos/36836555@N00/6972045592/"&gt;&lt;img border="0" alt="2012-04-27_01h26_16" src="http://static.flickr.com/7214/6972045592_5b9e9c0fc0_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The HTML client page is making an .getJSON() call back to the Web API service, which returns a list of contacts in JSON format, then uses jQuery templating to display the contacts in HTML format. That jQuery templating should probably be updated to use the newer JSRender system, but it doesn't really matter for this example, since we're just concerned about the services, not the HTML client.&lt;/p&gt;  &lt;h2&gt;Looking at the ASP.NET Web API's services using F12 developer tools&lt;/h2&gt;  &lt;p&gt;We're going to be using Fiddler2 in a bit, but since the simplest way to view the output of the Web API's JSON services is in a browser. In IE, you do that by pressing the F12 hotkey to display developer tools - it looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-04-27_02h01_20" href="http://www.flickr.com/photos/36836555@N00/6972045614/"&gt;&lt;img border="0" alt="2012-04-27_02h01_20" src="http://static.flickr.com/7236/6972045614_ab3804db65_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now switch to the Network view (or your browser's equivalent), start monitoring, and browse to /contacts (in my case the full URL is &lt;a title="http://localhost:33936/contacts" href="http://localhost:33936/contacts"&gt;http://localhost:33936/contacts&lt;/a&gt;, your port number will vary). IE prompts you to download the JSON file and the browser's address bar goes back to the previous. That's a little wacky - other browsers display the JSON as text - but the service call response is included in the results. Clicking on it to bring up the detailed view and showing the response body shows the JSON data:&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-04-27_02h09_00" href="http://www.flickr.com/photos/36836555@N00/7118123775/"&gt;&lt;img border="0" alt="2012-04-27_02h09_00" src="http://static.flickr.com/7213/7118123775_830f556245_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The JSON data returned is as follows (I removed some of the contacts from the list for brevity):&lt;/p&gt;  &lt;pre class="brush: js;"&gt;[ { &amp;quot;Address&amp;quot; : &amp;quot;1 Microsoft Way&amp;quot;,
    &amp;quot;City&amp;quot; : &amp;quot;Redmond&amp;quot;,
    &amp;quot;ContactId&amp;quot; : 1,
    &amp;quot;Email&amp;quot; : &amp;quot;gblock@microsoft.com&amp;quot;,
    &amp;quot;Name&amp;quot; : &amp;quot;Glenn Block&amp;quot;,
    &amp;quot;Self&amp;quot; : &amp;quot;contact/1&amp;quot;,
    &amp;quot;State&amp;quot; : &amp;quot;Washington&amp;quot;,
    &amp;quot;Twitter&amp;quot; : &amp;quot;gblock&amp;quot;,
    &amp;quot;Zip&amp;quot; : &amp;quot;98112&amp;quot;
  },
  { &amp;quot;Address&amp;quot; : &amp;quot;1 Microsoft Way&amp;quot;,
    &amp;quot;City&amp;quot; : &amp;quot;Redmond&amp;quot;,
    &amp;quot;ContactId&amp;quot; : 2,
    &amp;quot;Email&amp;quot; : &amp;quot;howard@microsoft.com&amp;quot;,
    &amp;quot;Name&amp;quot; : &amp;quot;Howard Dierking&amp;quot;,
    &amp;quot;Self&amp;quot; : &amp;quot;contact/2&amp;quot;,
    &amp;quot;State&amp;quot; : &amp;quot;Washington&amp;quot;,
    &amp;quot;Twitter&amp;quot; : &amp;quot;howard_dierking&amp;quot;,
    &amp;quot;Zip&amp;quot; : &amp;quot;98112&amp;quot;
  },
  { &amp;quot;Address&amp;quot; : &amp;quot;1 Microsoft Way&amp;quot;,
    &amp;quot;City&amp;quot; : &amp;quot;Redmond&amp;quot;,
    &amp;quot;ContactId&amp;quot; : 3,
    &amp;quot;Email&amp;quot; : &amp;quot;yavorg@microsoft.com&amp;quot;,
    &amp;quot;Name&amp;quot; : &amp;quot;Yavor Georgiev&amp;quot;,
    &amp;quot;Self&amp;quot; : &amp;quot;contact/3&amp;quot;,
    &amp;quot;State&amp;quot; : &amp;quot;Washington&amp;quot;,
    &amp;quot;Twitter&amp;quot; : &amp;quot;digthepony&amp;quot;,
    &amp;quot;Zip&amp;quot; : &amp;quot;98112&amp;quot;
  }]&lt;/pre&gt;

&lt;p&gt;That content's being returned from the ContactsController's Get action, which just returns a Queryable list:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public IQueryable&lt;contact&gt; Get()
{
    return this.repository.GetAll().AsQueryable();
}&lt;/pre&gt;

&lt;p&gt;Out of the box, ASP.NET Web API can format data in JSON and XML format, so the output is automatic depending on content negotiation. If you're familiar with ASP.NET Web API, this is all pretty standard stuff. If you're not, I recommend the ASP.NET Web API content section at &lt;a href="http://asp.net/web-api"&gt;http://asp.net/web-api&lt;/a&gt; and my &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;previous blog / screencast series&lt;/a&gt; on getting started with ASP.NET Web API.&lt;/p&gt;

&lt;p&gt;The point is that this sample is producing JSON data that we can display in our Windows 8 Metro application.&lt;/p&gt;

&lt;h2&gt;Creating a Windows 8 Metro style application using the Blank template&lt;/h2&gt;

&lt;p&gt;To create the Windows 8 Metro application, add a new project using the File / Add / New Project... dialog. Select the Visual C# / Windows Metro Style section, then pick the Blank Application template. I called mine ContactManagerMetro because I have no imagination.&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-04-27_00h49_24" href="http://www.flickr.com/photos/36836555@N00/7118123693/"&gt;&lt;img border="0" alt="2012-04-27_00h49_24" src="http://static.flickr.com/7215/7118123693_21e7434856_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why the Blank Application template? Good question. I started with the Split Application template, but it has existing data structures which are hierarchical (since the Split Application helps with navigating structured content), so it wasn't a good fit. I think the Blank Application template is a good start since it's nice and simple.&lt;/p&gt;

&lt;p&gt;This application is, as promised, rather blank. The main form is even called BlankPage.xaml, which while being rather descriptive of the initial state, seems unlikely to remain accurate for very long in most cases. Since we're just proving concepts at this point, though, I'm going to grit my teeth and leave the name as BlankPage.xaml. Focus.&lt;/p&gt;

&lt;h2&gt;Writing the Metro Application XAML&lt;/h2&gt;

&lt;p&gt;We've got a lot of options for how to display the contact information, but I think a good start is using the same kind of display that the original HTML view used. In the Metro XAML land, that's usually done using a ListView. Inside BlankPage.xaml's empty grid, I'm going to add the following ListView markup:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;GridView x:Name=&amp;quot;ContactList&amp;quot;&amp;gt;
    &amp;lt;GridView.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;StackPanel Width=&amp;quot;200&amp;quot; Height=&amp;quot;150&amp;quot; Margin=&amp;quot;10&amp;quot; Background=&amp;quot;#FF161C8F&amp;quot;&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Name}&amp;quot; FontSize=&amp;quot;24&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Address}&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding City}&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding State}&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Zip}&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Twitter}&amp;quot; /&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/GridView.ItemTemplate&amp;gt;
&amp;lt;/GridView&amp;gt;&lt;/pre&gt;

&lt;p&gt;This is pretty rudimentary, we'll clean it up later. The main reason I'm writing it now is to make sure I know what I'll be binding to, and for the above TextBlock binding values I just based the values off the contact properties returned by the service.&lt;/p&gt;

&lt;h2&gt;Calling the Web API service from our Metro Application&lt;/h2&gt;

&lt;p&gt;Calling the service is actually pretty straightforward. First, I'll use the System.Net.Http.HttpClient to call the service. As all external calls in WinRT are async, I need to handle that. Fortunately the async/await keywords make that really easy.&lt;/p&gt;

&lt;p&gt;Since our service returns JSON, I'm going to leverage the utility classes in the &lt;a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.data.json.aspx"&gt;Windows.Data.Json namespace&lt;/a&gt; to parse it. The code is a little repetitive and could definitely use some refactoring, but it handles the job of mapping JSON values to an anonymous object. &lt;a href="http://timheuer.com/blog/archive/2012/04/10/anonymous-type-binding-metro-style-app.aspx"&gt;Tim Heuer recently blogged about using that with anonymous type binding&lt;/a&gt;, and I liked his approach.&lt;/p&gt;

&lt;p&gt;With all the plumbing in place, I'll call this GetContacts() method from my OnNavigatedTo event.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;protected override void OnNavigatedTo(NavigationEventArgs e)
{
    GetContacts();
}

public async void GetContacts()
{
    var serviceuri = &amp;quot;http://localhost:33936/contacts&amp;quot;;
    var client = new System.Net.Http.HttpClient();

    var response = await client.GetAsync(serviceuri);
    if (response.IsSuccessStatusCode)
    {
        var data = await response.Content.ReadAsStringAsync();
        var contacts = JsonArray.Parse(data);

        var qry = from m in contacts
            select new
            {
                Name = m.GetObject()[&amp;quot;Name&amp;quot;].GetString(),
                Address = m.GetObject()[&amp;quot;Address&amp;quot;].GetString(),
                City = m.GetObject()[&amp;quot;City&amp;quot;].GetString(),
                State = m.GetObject()[&amp;quot;State&amp;quot;].GetString(),
                Zip = m.GetObject()[&amp;quot;Zip&amp;quot;].GetString(),
                Twitter = m.GetObject()[&amp;quot;Twitter&amp;quot;].GetString(),
            };

        ContactList.ItemsSource = qry;
    }
}&lt;/pre&gt;

&lt;p&gt;This calls into our service and displays the following data:&lt;/p&gt;

&lt;p&gt;&lt;a title="Screenshot" href="http://www.flickr.com/photos/36836555@N00/7118348855/"&gt;&lt;img border="0" alt="Screenshot" src="http://static.flickr.com/8148/7118348855_4dd084f29c_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hurrah! We got data from our service and viewed it in the app. It's pretty ugly, though. Let's clean up the formatting a bit so it matches the original app a little better. I'm using the underappreciated &amp;lt;Run&amp;gt; XAML element for that:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;&amp;lt;GridView x:Name=&amp;quot;ContactList&amp;quot;&amp;gt;
    &amp;lt;GridView.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;StackPanel Width=&amp;quot;250&amp;quot; Height=&amp;quot;150&amp;quot; Margin=&amp;quot;10&amp;quot; Background=&amp;quot;#FF161C8F&amp;quot;&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Name}&amp;quot; FontSize=&amp;quot;28&amp;quot; Margin=&amp;quot;10,20,10,0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Margin=&amp;quot;10,0&amp;quot;&amp;gt;
                    &amp;lt;Run Text=&amp;quot;{Binding Address}&amp;quot; /&amp;gt;, &amp;lt;Run Text=&amp;quot;{Binding City}&amp;quot; /&amp;gt;
                &amp;lt;/TextBlock&amp;gt;
                &amp;lt;TextBlock Margin=&amp;quot;10,0&amp;quot;&amp;gt;
                    &amp;lt;Run Text=&amp;quot;{Binding State}&amp;quot; /&amp;gt; &amp;lt;Run Text=&amp;quot;{Binding Zip}&amp;quot; /&amp;gt;
                &amp;lt;/TextBlock&amp;gt;
                &amp;lt;TextBlock Margin=&amp;quot;10,0&amp;quot;&amp;gt;
                    @&amp;lt;Run Text=&amp;quot;{Binding Twitter}&amp;quot; /&amp;gt;
                &amp;lt;/TextBlock&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/GridView.ItemTemplate&amp;gt;
&amp;lt;/GridView&amp;gt;&lt;/pre&gt;

&lt;p&gt;That at least organizes the text a bit:&lt;/p&gt;

&lt;p&gt;&lt;a title="Screenshot (2)" href="http://www.flickr.com/photos/36836555@N00/6972281294/"&gt;&lt;img border="0" alt="Screenshot (2)" src="http://static.flickr.com/7176/6972281294_a46d6cfafb_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's at least a decent start. Questions? Where should we go next?&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8413902" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=vnJ5fWXiI4E:rorOMPj8Qco:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=vnJ5fWXiI4E:rorOMPj8Qco:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=vnJ5fWXiI4E:rorOMPj8Qco:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=vnJ5fWXiI4E:rorOMPj8Qco:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=vnJ5fWXiI4E:rorOMPj8Qco:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=vnJ5fWXiI4E:rorOMPj8Qco:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=vnJ5fWXiI4E:rorOMPj8Qco:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/vnJ5fWXiI4E" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+Web+API/default.aspx">ASP.NET Web API</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/Windows+8/default.aspx">Windows 8</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/04/27/windows-8-and-asp-net-web-api-part-1-getting-started.aspx</feedburner:origLink></item><item><title>ASP.NET MVC Authentication - Global Authentication and Allow Anonymous</title><link>http://feedproxy.google.com/~r/jongalloway/~3/PflKwWXmQ50/asp-net-mvc-authentication-global-authentication-and-allow-anonymous.aspx</link><pubDate>Thu, 19 Apr 2012 02:29:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8396218</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8396218</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/04/18/asp-net-mvc-authentication-global-authentication-and-allow-anonymous.aspx#comments</comments><description>&lt;p&gt;As I was recently updating the Wrox Professional ASP.NET book for ASP.NET MVC 4, I thought about some of the common questions, tip, and tricks I've seen over the past few years, and thought it was time for a... quick blog series! Let's start with Global Authentication.&lt;/p&gt;  &lt;p&gt;ASP.NET MVC has &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx" mce_href="http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx"&gt;had an Account Controller since the ASP.NET MVC 1.0 preview releases&lt;/a&gt;; it handles login and registration. That, by itself, just allows users to get logged in - it doesn't do anything to restrict access. That's where the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx"&gt;AuthorizeAttribute&lt;/a&gt; comes into play. AuthorizeAttribute is a Filter attribute which can be placed on ASP.NET MVC actions or entire controllers to prevent unauthorized access. Attempting to access a restricted controller action when you're not authorized redirects you to login, as I previously described in quite gory detail in a previous post titled &lt;a href="http://weblogs.asp.net/jgalloway/archive/2011/04/28/looking-at-how-asp-net-mvc-authorize-interacts-with-asp-net-forms-authorization.aspx" mce_href="http://weblogs.asp.net/jgalloway/archive/2011/04/28/looking-at-how-asp-net-mvc-authorize-interacts-with-asp-net-forms-authorization.aspx"&gt;Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization&lt;/a&gt;. &lt;/p&gt;  &lt;h3&gt;Reminder: Don't use web.config to restrict access, use [Authorize]&lt;/h3&gt;  &lt;p&gt;&lt;em&gt;Note: This is old news to MVC veterans, but bears repeating because it continues to be a common question and is really important to get right.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;In ASP.NET Web Forms, requests mapped to physical files. There's an &lt;a href="http://msdn.microsoft.com/en-us/library/8d82143t.aspx" mce_href="http://msdn.microsoft.com/en-us/library/8d82143t.aspx"&gt;&amp;lt;authorization&amp;gt; element&lt;/a&gt;&amp;nbsp; in web.config which can be used to restrict file-based access. So this worked well for ASP.NET Web Forms and file-based authorization in general.&lt;/p&gt;  &lt;p&gt;But it's a very bad idea to use web.config based authorization in ASP.NET MVC, because URL's map to actions via routing, which can change. You may have multiple routes that map to the same controller action, or you may change routes over time. AuthorizeAttribute was built specifically for this purpose, because you can place your security directly on the resource (the action or controller). Change the routes all you want, the authorization rules go along with the actions. &lt;/p&gt;  &lt;p&gt;Another interesting note here is that, since ASP.NET Web Forms has supported routing since ASP.NET 4, you need to pay closer attention to securing routes there as well. K. Scott Allen discussed that in an MSDN Magazine article a few years ago, &lt;a href="http://msdn.microsoft.com/en-us/magazine/dd347546.aspx#id0070044" mce_href="http://msdn.microsoft.com/en-us/magazine/dd347546.aspx#id0070044"&gt;Routing with ASP.NET Web Forms&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;The progression of global authentication in ASP.NET MVC&lt;/h2&gt;  &lt;p&gt;The AuthorizeAttribute works pretty well, but you have to put it on every controller (or action, if you need to be that granular) that needs to be secured. That's tedious and error prone, and if you forget it, you've opened your site up to anonymous access. In many cases, it's preferable to restrict access to the entire site &lt;em&gt;except&lt;/em&gt; for the the Login and Register actions. That's become a little easier with each release, to the point where in ASP.NET MVC 4 I think it's finally about right.&lt;/p&gt;  &lt;p&gt;Rick Anderson wrote two comprehensive posts on this - and authorization in ASP.NET MVC in general - in a pair of posts covering security in ASP.NET MVC:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/rickandy/archive/2011/05/02/securing-your-asp-net-mvc-3-application.aspx" mce_href="http://blogs.msdn.com/b/rickandy/archive/2011/05/02/securing-your-asp-net-mvc-3-application.aspx"&gt;Securing your ASP.NET MVC 3 Application&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx" mce_href="http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx"&gt;Securing your ASP.NET MVC 4 App and the new AllowAnonymous Attribute&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;ASP.NET MVC 1 and 2 - Custom Controller Base&lt;/h2&gt;  &lt;p&gt;In the first post, Rick explains that prior to ASP.NET MVC 3, the recommended approach was to create a custom Controller base class with an [Authorize] attribute applied. This probably sounds more complicated than it is, because it's really easy:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Right-click the Controllers folder and add a new Controller. Call it something like AuthorizedController. &lt;/li&gt;    &lt;li&gt;Delete the Index action. &lt;/li&gt;    &lt;li&gt;Add the [Authorize] attribute to the class. &lt;/li&gt;    &lt;li&gt;Clean up the Using block at the top if you care about that kind of thing. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;End result:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    [Authorize]
    public class AuthorizedController : Controller
    {
    }
}&lt;/pre&gt;

&lt;p&gt;Now you can use this AuthorizedController base class for any other controllers in your application. Changing the HomeController base class to inherit from AuthorizedController will require authorization to view the site home:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    public class HomeController : AuthorizedController
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }

        //More actions here
    }
}&lt;/pre&gt;

&lt;p&gt;The downside is that you have to remember to do this, so unless you &lt;a href="http://blogs.msdn.com/b/webdevtools/archive/2009/01/29/t4-templates-a-quick-start-guide-for-asp-net-mvc-developers.aspx" mce_href="http://blogs.msdn.com/b/webdevtools/archive/2009/01/29/t4-templates-a-quick-start-guide-for-asp-net-mvc-developers.aspx"&gt;change the T4 templates&lt;/a&gt;, you're setting yourself up for an easy mistake down the road.&lt;/p&gt;

&lt;h2&gt;ASP.NET MVC 3 - Global Action Filters&lt;/h2&gt;

&lt;p&gt;ASP.NET MVC 3 made it easy to apply an action filter to all actions in your application. If you look in the Global.asax in an new ASP.NET MVC 3 (or later) application, you'll see a RegisterGlobalFilters method.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}&lt;/pre&gt;

&lt;p&gt;To require authorization throughout your application, you could just register AuthorizationAttribute, right?&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new AuthorizeAttribute());
}&lt;/pre&gt;

&lt;p&gt;Unfortunately, this works a little too well - it's global, so users can't login. But, really, really secure, right?&lt;/p&gt;

&lt;p&gt;Rick proposed a custom LoginAuthorizeAttribute which inherited from AuthorizeAttribute but added an exception for the AccountController, but Levi Broderick (an ASP.NET team member who's a whiz with web security) recommended using a filter to whitelist actions which should be available for anonymous access.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System.Web.Mvc;
using MvcGlobalAuthorize.Controllers;

namespace MvcGlobalAuthorize.Filters {
    public sealed class LogonAuthorize : AuthorizeAttribute {
        public override void OnAuthorization(AuthorizationContext filterContext) {
            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            if (!skipAuthorization) {
                base.OnAuthorization(filterContext);
            }
        }
    }
}&lt;/pre&gt;

&lt;p&gt;So now you'd register LogonAuthorize as a global filter, and to allow access to an action, you'll need that AllowAnonymousAttribute. Since it's just a marker attribute, there's no actual code - just attribute usage settings.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;using System;&lt;/pre&gt;

&lt;pre class="brush: csharp;"&gt;[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, 
                AllowMultiple = false, Inherited = true)]&lt;/pre&gt;

&lt;pre class="brush: csharp;"&gt;public sealed class AllowAnonymousAttribute : Attribute { }&lt;/pre&gt;

&lt;h2&gt;ASP.NET MVC 4 and the AllowAnonymous attribute&lt;/h2&gt;

&lt;p&gt;The good news is that this is even easier in ASP.NET MVC 4, because it's baked in. By baked in, I mean that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There's a built-in &lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/87e88d0446a2#src%2fSystem.Web.Mvc%2fAllowAnonymousAttribute.cs" mce_href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/87e88d0446a2#src%2fSystem.Web.Mvc%2fAllowAnonymousAttribute.cs"&gt;AllowAnonymousAttribute&lt;/a&gt; in the the System.Web.Mvc namespace which whitelists actions for anonymous access &lt;/li&gt;

  &lt;li&gt;The AuthorizeAttribute filter has built-in logic that allows access to actions decorated with the AllowAnonymousAttribute &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means that you can just register the AuthorizeAttribute as a global filter and put the AllowAnonymousAttribute on any actions that should be public. &lt;/p&gt;

&lt;p&gt;If you use the AllowAnonymousAttribute without registering AuthorizeAttribute there's no effect. For that reason, the default AccountController in a new ASP.NET MVC 4 project has [AllowAnonymous] on all the actions that should always be public:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogin(LoginModel model, string returnUrl)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Login(LoginModel model, string returnUrl)

    public ActionResult LogOff()

    [AllowAnonymous]
    public ActionResult Register()

    [AllowAnonymous]
    [HttpPost]
    public ActionResult JsonRegister(RegisterModel model)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Register(RegisterModel model)

    public ActionResult ChangePassword()

    [HttpPost]
    public ActionResult ChangePassword(ChangePasswordModel model)

    public ActionResult ChangePasswordSuccess()
}&lt;/pre&gt;

&lt;p&gt;That works because, as mentioned above, the AuthorizeAttribute has the following logic (as you can see &lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/87e88d0446a2#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs" mce_href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/87e88d0446a2#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs"&gt;from the code on CodePlex&lt;/a&gt;): &lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true)
	|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true);

if (skipAuthorization)
{
    return;
}&lt;/pre&gt;

&lt;p&gt;Note: I actually started looking into this in detail because I was wondering how the AllowAnonymousAttribute was able to bypass the Authorization check, and was surprised to see that it didn't have any code at all. I wasn't alone here, I noticed &lt;a href="http://www.davidhayden.me/blog/asp.net-mvc-4-allowanonymous-attribute-and-authorize-attribute" mce_href="http://www.davidhayden.me/blog/asp.net-mvc-4-allowanonymous-attribute-and-authorize-attribute"&gt;David Hayden looked into this as well&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested in more information on ASP.NET MVC security and the history of the AnonymousAttribute, I highly recommend Rick's posts listed above. He goes into a lot more detail - with some excellent input from Levi - on what not to do (e.g. put security logic into routing) and further considerations like requiring HTTPS globally.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8396218" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=PflKwWXmQ50:W_9gS6tE-0U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=PflKwWXmQ50:W_9gS6tE-0U:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=PflKwWXmQ50:W_9gS6tE-0U:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=PflKwWXmQ50:W_9gS6tE-0U:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=PflKwWXmQ50:W_9gS6tE-0U:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=PflKwWXmQ50:W_9gS6tE-0U:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=PflKwWXmQ50:W_9gS6tE-0U:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/PflKwWXmQ50" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/04/18/asp-net-mvc-authentication-global-authentication-and-allow-anonymous.aspx</feedburner:origLink></item><item><title>I've joined the Windows Azure technical evangelist team</title><link>http://feedproxy.google.com/~r/jongalloway/~3/ESiJy4b6pnU/i-ve-joined-the-windows-azure-technical-evangelist-team.aspx</link><pubDate>Wed, 18 Apr 2012 21:20:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8395983</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8395983</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/04/18/i-ve-joined-the-windows-azure-technical-evangelist-team.aspx#comments</comments><description>&lt;p&gt;I've been at Microsoft for a little over two years now, working in groups that focused primarily on publishing online content for developers. In addition to the obvious things, there's a lot of work that goes on behind the scenes in creating and maintaining content&amp;nbsp; - maintaining and improving existing content, planning content for unreleased platforms and products, handling dozens of spoken languages and several programming languages, etc. It's been a pleasure working with some real professionals. I've also enjoyed working in a small but dynamic group that's focused on the developer community. During that time I had two excellent bosses, Scott Hanselman and Pete Brown. Both really made it fun to show up to work every day. Well, I work from home, but still.&lt;/p&gt;
  
&lt;p&gt;I'm excited about my new position in the Windows Azure technical evangelist team.&lt;/p&gt;
  &lt;h2&gt;Wait, what? Azure?&lt;/h2&gt;  
&lt;p&gt;Yep, Azure. Let me explain why.&lt;/p&gt;
  &lt;h3&gt;Azure Application Platform Team includes ASP.NET, IIS, etc.&lt;/h3&gt;  
&lt;p&gt;First, you'll recall that Scott Guthrie heads the Azure Application Platform team, and &lt;a href="http://msdn.microsoft.com/en-us/hh824721" mce_href="http://msdn.microsoft.com/en-us/hh824721"&gt;that group includes ASP.NET and IIS&lt;/a&gt;. In the year since that transition, I've been really happy with where I've seen Microsoft's web platform going. The ASP.NET team has been cranking out some great stuff for the ASP.NET 4.5 / ASP.NET MVC 4 / ASP.NET Web Pages 2 wave (easier to just call it &lt;a href="http://www.asp.net/vnext" mce_href="http://www.asp.net/vnext"&gt;ASP.NET vNext&lt;/a&gt;). Oh, and they just open sourced a whole lot of code. So if anyone was concerned that ASP.NET would stall out in this new organization, I think this past year would allay that fear.&lt;/p&gt;
  &lt;h3&gt;Azure as a good influence on Microsoft&lt;/h3&gt;  
&lt;p&gt;And in fact, it seems like the influence of running Azure as a hosting platform has opened Microsoft's web development horizons a good amount. We've got people like &lt;a href="http://channel9.msdn.com/Events/windowsazure/learn/Interview-with-Glenn-Block-Talking-About-Node-js-on-Windows-Azure" mce_href="http://channel9.msdn.com/Events/windowsazure/learn/Interview-with-Glenn-Block-Talking-About-Node-js-on-Windows-Azure"&gt;Glenn Block working with Node.js&lt;/a&gt;, Microsoft shipping code on GitHub (&lt;a href="https://github.com/WindowsAzure/" mce_href="https://github.com/WindowsAzure/"&gt;all the Azure sdk's are on GitHub&lt;/a&gt;), &lt;a href="http://blogs.technet.com/b/port25/archive/2011/10/11/microsoft-hadoop-and-big-data.aspx" mce_href="http://blogs.technet.com/b/port25/archive/2011/10/11/microsoft-hadoop-and-big-data.aspx"&gt;Hadoop support on both Azure and Windows Server&lt;/a&gt;, etc. So if anything, Azure is really broadening Microsoft's perspective on web development. I hadn't expected that at all.&lt;/p&gt;
  &lt;h3&gt;Azure future&lt;/h3&gt;  
&lt;p&gt;Well. All I can say here is that I'm extremely excited about where Azure is going as a platform. As &lt;a href="http://msdn.microsoft.com/en-us/hh824721" mce_href="http://msdn.microsoft.com/en-us/hh824721"&gt;Scott Guthrie said in MSDN Flash recently&lt;/a&gt;, "You will see even more significant updates and features in Windows Azure in the months ahead." There are a lot of things coming together here that are making Azure very interesting for me as a developer, and I want to be in on it. Stay tuned.&lt;/p&gt;
  &lt;h2&gt;Windows Azure Technical Evangelist team&lt;/h2&gt;  
&lt;p&gt;This is an cool team. I'm helping (new Microsoft employee) &lt;a href="http://bradygaster.com/"&gt;Brady Gaster&lt;/a&gt; with this summer's Web Camps, learning some interesting Windows 8 dev from &lt;a href="http://nickharris.net/" mce_href="http://nickharris.net/"&gt;Nick Harris&lt;/a&gt;, got to meet up with &lt;a href="http://blog.ntotten.com/" mce_href="http://blog.ntotten.com/"&gt;Nathan Totten&lt;/a&gt; (I'd used his Facebook SDK in the past), and I'm just getting started. Oh, and &lt;a href="http://blog.syntaxc4.net/" mce_href="http://blog.syntaxc4.net/"&gt;Cory Fowler&lt;/a&gt; just joined up too, focusing on the open source community on Azure including PHP and Node.js. And lots of other smart folks, all focusing on different applications of Azure and the Azure application platform. &lt;a href="http://jamesconard.com/" mce_href="http://jamesconard.com/"&gt;James Conard&lt;/a&gt; has put a really good team together, and it's really energizing to be a part of it.&lt;/p&gt;
  
&lt;p&gt;Nick and Nate just took over the Cloud Cover show on Channel 9 and interviewed me, along with the other three new team members: &lt;a href="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-76-Meet-our-new-additions-to-the-Windows-Azure-Technical-Evangelist-Team" mce_href="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-76-Meet-our-new-additions-to-the-Windows-Azure-Technical-Evangelist-Team"&gt;Cloud Cover - Episode 76 - Meet our new additions to the Windows Azure Technical Evangelist Team&lt;/a&gt; (I'm on around 14:40).&lt;/p&gt;
 &lt;iframe style="width: 512px; height: 288px;" src="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-76-Meet-our-new-additions-to-the-Windows-Azure-Technical-Evangelist-Team/player?w=512&amp;amp;h=288" frameBorder="0" scrolling="no" mce_src="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-76-Meet-our-new-additions-to-the-Windows-Azure-Technical-Evangelist-Team/player?w=512&amp;amp;h=288"&gt;&lt;/iframe&gt;  &lt;h2&gt;What's new for Jon&lt;/h2&gt;  
&lt;p&gt;I'll be continuing to focus on ASP.NET as a platform. I like ASP.NET, and I like helping other people who are using it. Azure is a good place to put ASP.NET apps, so more ASP.NET apps helps Azure. So that means I'll continue to do thing's I've been doing in the past - blogging, speaking, writing, tutorials, screencasts about ASP.NET. But with more options for scale, travel budget, opportunities for collaboration with other groups, etc.&lt;/p&gt;
  
&lt;p&gt;For example, I'll be speaking at a &lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032510540&amp;amp;Culture=en-US" mce_href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032510540&amp;amp;Culture=en-US"&gt;Web Camp in Boston on May 10&lt;/a&gt; as part of the Web Camps tour that Brady's putting together. Brady invited me on Web Camps TV to help introduce Web Camps 2012:&lt;/p&gt;
  
&lt;p&gt;&lt;a href="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012" mce_href="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012"&gt;Jon Galloway Helps Introduce Web Camps 2012&lt;/a&gt;&lt;/p&gt;
  &lt;iframe style="width: 512px; height: 288px;" src="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012/player?w=512&amp;amp;h=288" frameBorder="0" scrolling="no" mce_src="http://channel9.msdn.com/Shows/Web+Camps+TV/Jon-Galloway-Helps-Introduce-Web-Camps-2012/player?w=512&amp;amp;h=288"&gt;&lt;/iframe&gt;  
&lt;p&gt;I've been doing some behind the scenes work on the ASP.NET site to make content easier to find and consume (e.g. HTML5 video support, input on responsive design). I also help with content for ASP.NET releases, like edits and publishing the ASP.NET MVC release notes, setting up things like the ASP.NET Web API content area, etc. That won't change.&lt;/p&gt;
  
&lt;p&gt;So my focus stays on ASP.NET as a platform - whether you host it on Azure, IIS, or &lt;a href="http://www.asp.net/web-api/overview/hosting-aspnet-web-api/self-host-a-web-api" mce_href="http://www.asp.net/web-api/overview/hosting-aspnet-web-api/self-host-a-web-api"&gt;wherever else you crazy kids decide to put it&lt;/a&gt;.&lt;/p&gt;
  
&lt;p&gt;But, as I said, I joined the Azure evangelist team because I'm excited abou it, so of course I'll be using it and talking about it as I do. For intstance, I'm thinking there are a lot of opportunities to spin up sample apps and services in Azure to show what I'm talking about.&lt;/p&gt;
&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8395983" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=ESiJy4b6pnU:x9qkiEcgDvg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=ESiJy4b6pnU:x9qkiEcgDvg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=ESiJy4b6pnU:x9qkiEcgDvg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=ESiJy4b6pnU:x9qkiEcgDvg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=ESiJy4b6pnU:x9qkiEcgDvg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=ESiJy4b6pnU:x9qkiEcgDvg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=ESiJy4b6pnU:x9qkiEcgDvg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/ESiJy4b6pnU" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/04/18/i-ve-joined-the-windows-azure-technical-evangelist-team.aspx</feedburner:origLink></item><item><title>Thoughts on ASP.NET MVC, ASP.NET Web API, and ASP.NET Web Pages (Razor) open source announcements</title><link>http://feedproxy.google.com/~r/jongalloway/~3/wTJg7q2f8gw/thoughts-on-asp-net-mvc-asp-net-web-api-and-asp-net-web-pages-razor-open-source-announcements.aspx</link><pubDate>Sat, 31 Mar 2012 00:34:17 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8370870</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8370870</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/30/thoughts-on-asp-net-mvc-asp-net-web-api-and-asp-net-web-pages-razor-open-source-announcements.aspx#comments</comments><description>&lt;p&gt;I'm really excited by the big announcements earlier this week:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The source for ASP.NET Web API and ASP.NET Web Pages (Razor) were released under Apache v2 license &lt;/li&gt;    &lt;li&gt;ASP.NET Web API, ASP.NET Web Pages, and ASP.NET MVC (which was already released under MsPL license) will accept community contributions &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I'm a big fan of both ASP.NET and open source, so it's exciting to see two of my favorite techy things hanging out at the same party. By now, you've likely read a few post with the actual details, very likely by one or more person named Scott, which contains some actual facts and some of the history. So here are a few recommended posts, followed by some additional commentary.&lt;/p&gt;  &lt;h2&gt;Must Read Posts&lt;/h2&gt;  &lt;p&gt;Scott Guthrie: &lt;a href="http://weblogs.asp.net/scottgu/archive/2012/03/27/asp-net-mvc-web-api-razor-and-open-source.aspx"&gt;ASP.NET MVC, Web API, Razor and Open Source&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Scott Guthrie's announcement explains what's been released and how to get involved.&lt;/p&gt;  &lt;p&gt;Scott Hansleman: &lt;a href="http://www.hanselman.com/blog/ASPNETMVC4ASPNETWebAPIAndASPNETWebPagesV2RazorNowAllOpenSourceWithContributions.aspx"&gt;ASP.NET MVC 4, ASP.NET Web API and ASP.NET Web Pages v2 (Razor) now all open source with contributions&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Scott Hanselman's post is worth reading just for the animated GIF's, but he also describes some of the history and answers some common / likely questions, like &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Why are you doing this? &lt;/li&gt;    &lt;li&gt;Are you going to open source more things in ASP.NET? &lt;/li&gt;    &lt;li&gt;Why isn’t ASP.NET Web Forms open sourced? &lt;/li&gt;    &lt;li&gt;What about Mono? &lt;/li&gt;    &lt;li&gt;Why not on GitHub? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Phil Haack: &lt;a href="http://haacked.com/archive/2012/03/29/asp-net-mvc-now-accepting-pull-requests.aspx"&gt;ASP.NET MVC Now Accepting Pull Requests&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Phil gives some good background on what was involved in making it possible for these products to accept external contribution. More on that later.&lt;/p&gt;  &lt;p&gt;Jimmy Bogard: &lt;a href="http://lostechies.com/jimmybogard/2012/03/28/asp-net-mvc-web-api-razor-and-open-source-and-what-it-means/"&gt;ASP.NET MVC, Web API, Razor and Open Source and what it means&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I really like Jimmy's post. He starts off by clarifying that open source has never required accepting external contributions, then asks and answers some good questions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Will the quality of the product be adversely affected because the team accepts contributions? &lt;/li&gt;    &lt;li&gt;Will some yahoo be able to sidestep my current feedback channel and take the product in some other (wrong) direction? &lt;/li&gt;    &lt;li&gt;Will my pull request get accepted? &lt;/li&gt;    &lt;li&gt;Will someone else’s changes be supported? &lt;/li&gt;    &lt;li&gt;Are we in store for human sacrifice, dogs and cats living together, mass hysteria? &lt;/li&gt;    &lt;li&gt;Can we trust these products now? &lt;/li&gt;    &lt;li&gt;Is this a Good Thing? &lt;/li&gt;    &lt;li&gt;Why CodePlex and not GitHub? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I'm going to assume you're familiar with the above for the rest of this post. So here's what I think about this - and as a reminder, these are my own opinions, not Microsoft position or policy or whatever.&lt;/p&gt;  &lt;h2&gt;Source visibility - What's really changed&lt;/h2&gt;  &lt;p&gt;.NET framework has never been obfuscated. We all take that for granted, but it's been really useful to me throughout my .NET development career. Come to think of it, the Visual Basic 6 (and previous versions) source code wasn't available to me - and even if it had been, it wasn't written in Visual Basic so I wouldn't have been able to read it. So there are two nice things there:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The fact that .NET and the frameworks built on top of it have always been available to decompile &lt;/li&gt;    &lt;li&gt;Just about all of .NET and frameworks, such as ASP.NET assemblies, are written in .NET so that they can be decompiled into something .NET developers can readily understand &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Several times I week, I pop open ILSpy to either figure out or verify something about how ASP.NET works, often to answer a question that'd be really difficult otherwise. It's not that there isn't plenty of documentation available - there is - but often the best way to learn how code works is to look at the code.&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-03-29 22h29_25" href="http://www.flickr.com/photos/36836555@N00/6882578562/"&gt;&lt;img border="0" alt="2012-03-29 22h29_25" src="http://farm7.static.flickr.com/6049/6882578562_c638dedaa2_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;While these are best disassemblers out there have been third party (e.g. Reflector, ILSpy, ), &lt;a href="http://msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.71).aspx"&gt;Microsoft's provided ildasm.exe from back in the .NET 1.1 days&lt;/a&gt; (maybe earlier?).&lt;/p&gt;  &lt;p&gt;We've had symbols available, too, so we could debug directly into .NET source code as needed. You can point Visual Studio at Microsoft's public symbol servers and debug right into .NET source code in a couple of minutes.&lt;/p&gt;  &lt;p&gt;&lt;a title="2012-03-30 00h02_14" href="http://www.flickr.com/photos/36836555@N00/7028800905/"&gt;&lt;img border="0" alt="2012-03-30 00h02_14" src="http://farm8.static.flickr.com/7065/7028800905_b2984029ac_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And that doesn't even get into what IntelliTrace does if you've got a Visual Studio Ultimate license.&lt;/p&gt;  &lt;p&gt;So, the point is that we've always been able to &lt;em&gt;see&lt;/em&gt; the source code for pretty much anything most developers would care about. ASP.NET MVC moved things along by actually releasing the ASP.NET MVC code under an open source license, but other than maybe the Mono project, I'm not aware of anyone really taking heavy advantage of it. I'd personally be really happy to hear that I'm wrong here, but just haven't heard of people doing things like building custom versions of ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;So what's the point, then?&lt;/p&gt;  &lt;p&gt;For me, as a consumer, &lt;strong&gt;code that's released under an open license gives me options and peace of mind&lt;/strong&gt;. It lets me know that, regardless of what happens to the project, the source is available for me and other users to carry it forward. Several of my favorite open source applications are forks, and that's something I consider when I invest my time in learning a new framework or application.&lt;/p&gt;  &lt;p&gt;So, back to the earlier question... if we've always been able to view the code, what's really changed?&lt;/p&gt;  &lt;p&gt;Two big things:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Much more visibility into the development process &lt;/li&gt;    &lt;li&gt;Acceptance of community contributions &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;Instant Visibility&lt;/h2&gt;  &lt;p&gt;You might think that, as a Microsoft employee, I have free run of the Microsoft source code. Or at least the .NET framework code. Certainly the ASP.NET code repository, right? No, I don't. I subscribe to the source control check-in e-mails, but I've historically kept up with what was going on by talking with the team and keeping up with announcements on the ASP.NET Insiders list.&lt;/p&gt;  &lt;p&gt;But over time, that's become less of a thing. As Scott Koon said after the last MVP Summit, he hadn't really heard a single big surprise on what the ASP.NET team was working on... and that's a very good thing. The team's been very open as to what they're up to, what they're thinking about doing in the future, etc.&lt;/p&gt;  &lt;p&gt;And this new open source change takes things to a new level there, because they're working in a public repository. So rather than waiting on big releases - or even pre-releases - anyone can watch the checkins as they happen. That's a big deal.&lt;/p&gt;  &lt;h2&gt;Accepting community contributions&lt;/h2&gt;  &lt;p&gt;Phil Haack's written some interesting posts recently on open source. His post listed earlier highlighted the difference between code that's released under an open source license and an open source project. As Jimmy Bogard points out, there's nothing about any accepted open source definition that requires accepting community contributions. Nobody would dispute that there are huge potential benefits to code and product quality if you can accept community contributions, but a decision that needs to be made by those who run the project.&lt;/p&gt;  &lt;p&gt;But many of the ASP.NET devs run or participate in open source proects, so why wouldn't they just open things up?&lt;/p&gt;  &lt;p&gt;Oh, it's stupid company politics and blasted lawyers. Well, that's the simplistic thinking, anyhow. Okay, fine, the devs would like things to be open, but pointy headed bosses ruin it. Oh, and it takes a long time to change minds and steer big ships or something. It's not that simple, though.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;[Disclaimer: Personal opinions following. My whole blog is generally my personal opinions unless I say otherwise, but I want to make that really clear.]&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Stepping back a bit - and speaking completely for myself, and not Microsoft or any future or previous employers here - businesses that sell some kind of intellectual property (as in they paid someone's salary to create something like digital media and software) need to be careful in giving things away, in ways you wouldn't expect. I have several relatives and close friends who make or have made their livings as musicians, and have explained that it's possible to do something wrong and suddenly your hit becomes public domain and your kids don't go to college. It's the same kind of thing with software - companies that want to give things away need to navigate a complex (bizarre?) legal system that handles intellectual property in non-intuitive ways.&lt;/p&gt;  &lt;p&gt;Phil Haack's blog post (&lt;a href="http://haacked.com/archive/2012/03/28/asp-net-mvc-now-accepting-pull-requests.aspx"&gt;ASP.NET MVC Now Accepting Pull Requests&lt;/a&gt;) spells this out well:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I also want to take a moment and credit the lawyers, who are often vilified, for their work in making this happen.&lt;/p&gt;    &lt;p&gt;One of my favorite bits of wisdom Scott Guthrie taught me is that the lawyers’ job is to protect the company and reduce risk. &lt;strong&gt;If lawyers had their way, we wouldn’t do anything because that’s the safest choice.&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;But it turns out that the biggest threat to a company’s long term well-being is doing nothing. Or being paralyzed by fear. And fortunately, there are some lawyers at Microsoft who get that. And rather than looking for reasons to say NO, they looked for reasons to say YES! And looked for ways to convince their colleagues.&lt;/p&gt;    &lt;p&gt;I spent a lot of time with these lawyers poring over tons of legal documents and such. Learning more about copyright and patent law than I ever wanted to. But united with a goal of making this happen.&lt;/p&gt;    &lt;p&gt;These are the type of lawyers you want to work with.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Five years ago (long before I worked at Microsoft) I wrote a blog post titled &lt;a href="http://weblogs.asp.net/jgalloway/archive/2007/05/02/why-microsoft-can-t-ship-open-source-code.aspx"&gt;Why Microsoft can't ship open source code&lt;/a&gt; which talks about some of the risks a company takes on in shipping code they didn't write:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;To understand the code pedigree problem, let's talk about the nightmare scenario. Let's say Microsoft took my advice and shipped Paint.NET as a Windows Vista Ultimate Extra. Unbeknownst to Microsoft - or even the Paint.NET project leads - a project contributor had copied some GPL code and included it in a patch submission (either out of ignorance or as with malice aforethought). Two years later, a competitor runs a binary scan for GPL code and serves Microsoft with a lawsuit for copyright infringement. Microsoft is forced to pay eleventy bajillion dollars and damages. Perhaps even worse, they're hit with an injunction which prevents selling the offending application, which requires recalling shrinkwrapped boxes and working with computer vendors who've got the software pre-installed on computers in their inventory. All for shipping a simple paint program.&lt;/p&gt;    &lt;p&gt;So, the risk is too great to justify the small reward.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The point is that, while there are obvious benefits to a company in shipping source code they didn't write, there are risks and costs. There's a good chance that your company doesn't open source all (or any?) of the software you write for these reasons. It's not necessarily because the company leadership / bosses / lawyers are stupid or bad, it's because it's a hard problem.&lt;/p&gt;  &lt;p&gt;This doesn't even get into all the other costs, like the time and effort required to support (or continually explain why you don't support) unreleased code, review pull requests, move from systems that work really well internally to systems that are externally visible and accessible, move from source practices that have been optimized for a centralized team to an open source model, etc.&lt;/p&gt;  &lt;p&gt;So I for one am profoundly thankful to all those who have done the work to get things worked out legally to both technically.&lt;/p&gt;  &lt;h2&gt;Where Next?&lt;/h2&gt;  &lt;h3&gt;Lurking&lt;/h3&gt;  &lt;p&gt;The simplest way to take advantage of this is to watch changes on the live repository. It's easy to see what's being worked on by watching public pages:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://aspnetwebstack.codeplex.com/workitem/list/basic"&gt;The Issue Tracker&lt;/a&gt; [&lt;a href="http://aspnetwebstack.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2fworkitem%2faspnetwebstack"&gt;RSS&lt;/a&gt;] &lt;/li&gt;    &lt;li&gt;&lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/list/changesets"&gt;Source code changesets&lt;/a&gt; [&lt;a href="http://aspnetwebstack.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2fsourcecontrol%2faspnetwebstack"&gt;RSS&lt;/a&gt;] &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Using&lt;/h3&gt;  &lt;p&gt;If you're interested in using code from the live repository, there are some directions here: &lt;a href="http://aspnetwebstack.codeplex.com/documentation"&gt;http://aspnetwebstack.codeplex.com/documentation&lt;/a&gt;. A couple notes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The directions show how to get the source code using a git client, which is a good idea if you're going to contribute back. If you just want to use the code, you can download a zip of the latest source (or any changeset) using the Download link on the &lt;a href="http://aspnetwebstack.codeplex.com/SourceControl/list/changesets"&gt;Source Control tab&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Make sure you note the SkipStrongNames step which lets you run unit tests against delay-signed binaries. &lt;/li&gt;    &lt;li&gt;If you're using Visual Studio 2010 SP1, the Runtime.sln handles package restore. If not, you'll need to follow the build.cmd directions to handle that. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Contributing&lt;/h3&gt;  &lt;p&gt;The first thing that often comes to mind when talking about contributing to an open source project is with surprise deliveries of random code. I've found - after having participating in a lot of open source projects - that is not the best way to get involved in any project. &lt;a href="http://aspnetwebstack.codeplex.com/wikipage?title=Contributing"&gt;The team's listed some good ways to get started&lt;/a&gt;, including bug reports and contributing tests. I try to do this kind of thing on projects I'm getting started with - it's a good way to get familiar with the source code and the way the project's run, which is an important first step.&lt;/p&gt;  &lt;p&gt;Miguel de Icaza has a great post on &lt;a href="http://tirania.org/blog/archive/2010/Dec-31.html"&gt;Open Source Contribution Etiquette&lt;/a&gt; which is great background on how to get started in contributing to a project.&lt;/p&gt;  &lt;p&gt;If you want to contribute code, the team has listed &lt;a href="http://aspnetwebstack.codeplex.com/wikipage?title=Contributing"&gt;some important steps&lt;/a&gt;. The whole list is important, but I want to point out one that thing - the Contributor License Agreement. It's a pretty short form (11-12 blanks to fill in, including date and signature) that essentially (I am not a lawyer) says who you are and that you're granting the rights to the code you're contributing.&lt;/p&gt;  &lt;p&gt;Oh, and if you're interested in contributing to Mono, &lt;a href="http://tirania.org/blog/archive/2012/Mar-28.html"&gt;they're looking for some help in integrating this new code&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Exciting times!&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8370870" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=wTJg7q2f8gw:7zZJNU9lRFQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=wTJg7q2f8gw:7zZJNU9lRFQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=wTJg7q2f8gw:7zZJNU9lRFQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=wTJg7q2f8gw:7zZJNU9lRFQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=wTJg7q2f8gw:7zZJNU9lRFQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=wTJg7q2f8gw:7zZJNU9lRFQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=wTJg7q2f8gw:7zZJNU9lRFQ:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/wTJg7q2f8gw" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/30/thoughts-on-asp-net-mvc-asp-net-web-api-and-asp-net-web-pages-razor-open-source-announcements.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series Part 6: Authorization</title><link>http://feedproxy.google.com/~r/jongalloway/~3/RUx_4-n7Pxc/asp-net-web-api-screencast-series-part-6-authorization.aspx</link><pubDate>Fri, 23 Mar 2012 23:55:08 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8361325</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8361325</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-6-authorization.aspx#comments</comments><description>&lt;p&gt;We're concluding a six part series on ASP.NET Web API that accompanies the getting started screencast series. This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;Part 1&lt;/a&gt; we looked at what ASP.NET Web API is, why you'd care, did the File / New Project thing, and did some basic HTTP testing using browser F12 developer tools.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx"&gt;Part 2&lt;/a&gt; we started to build up a sample that returns data from a repository in JSON format via GET methods.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx"&gt;Part 3&lt;/a&gt;, we modified data on the server using DELETE and POST methods.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx"&gt;Part 4&lt;/a&gt;, we extended on our simple querying methods form Part 2, adding in support for paging and querying.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-5-custom-validation.aspx"&gt;Part 5&lt;/a&gt;, we added support for Data Annotation based validation using an Action Filter.&lt;/p&gt;  &lt;p&gt;In Part 6, we'll require authentication using the built-in Authorization Filter.&lt;/p&gt; &lt;video height="525" width="644&amp;quot;" controls src="http://content5.catalog.video.msn.com/e2/ds/fc66e2f8-3d37-4efb-aa64-26d3c7810ea1.mp4"&gt;&lt;object id="SilverlightMediaPlayer" style="width:644px;height:525px;" autoupdate="true" data="data:application/x-silverlight-2," type="application/x-silverlight-2"&gt; 	&lt;param name="MinRuntimeVersion" value="2.0.31005.0" /&gt; 	&lt;param name="source" value="http://asp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002" /&gt; 	&lt;param name="InitParams" value="extendedfeatures=false,videoid=37168,videowidth=644,videoheight=525" /&gt; 	&lt;/object&gt;&lt;/video&gt;  &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/authorization"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;h2&gt;Requiring Authorization using the Authorization Filter&lt;/h2&gt;  &lt;p&gt;In Part 5, we use a custom Global Action Filter to enforce validation on every Action. In this (final) part, we'll use the built-in Authorize Filter. As with other Filters, they can be applied at the Action, Controller, or Global levels. In this case, we'll add it at the controller level by adding the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.http.filters.authorizationfilterattribute(v=vs.108).aspx"&gt;AuthorizationFilter attribute&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false; highlight: [1];"&gt;[Authorize] 
public class CommentsController : ApiController  
{ 
    ...
}&lt;/pre&gt;

&lt;p&gt;That's it from the server side. If a client makes an unauthorized request, the AuthorizationFilter does the only thing that makes sense for an HTTP API - it returns an HTTP Status Code 401, Authorization Required. Again, we're back to the value of using HTTP for an API - we don't need to arrange anything, any client on any platform will know what an HTTP 401 response means.&lt;/p&gt;

&lt;h2&gt;Handling Redirection on the Client&lt;/h2&gt;

&lt;p&gt;Many websites (and web frameworks) handle authorization by doing a server-side redirection to a login page. I wrote an in-depth post about &lt;a href="http://weblogs.asp.net/jgalloway/archive/2011/04/28/looking-at-how-asp-net-mvc-authorize-interacts-with-asp-net-forms-authorization.aspx"&gt;how ASP.NET MVC handles authorization redirection&lt;/a&gt; - internally an HttpUnauthorizedResult (HTTP 401) is intercepted by the FormsAuthenticationModule, which redirects to Login URL specified in web.config.&lt;/p&gt;

&lt;p&gt;None of that makes sense from an HTTP API perspective, though. HTTP API's return HTTP Responses to clients, which include things like Status Codes, Response Body, and Headers. It's up to the client to decide what to do when they get a 401. In this JavaScript / browser based sample, we'll just redirect to the login page on the client.&lt;/p&gt;

&lt;pre class="brush: js; auto-links: false; highlight: [11,12];"&gt;$(function () { 
    $(&amp;quot;#getCommentsFormsAuth&amp;quot;).click(function () { 
        viewModel.comments([]); 
        $.ajax({ url: &amp;quot;/api/comments&amp;quot;, 
            accepts: &amp;quot;application/json&amp;quot;, 
            cache: false, 
            statusCode: { 
                200: function(data) { 
                    viewModel.comments(data); 
                }, 
                401: function(jqXHR, textStatus, errorThrown) { 
                    self.location = '/Account/Login/'; 
                } 
            } 
        }); 
    }); 
});&lt;/pre&gt;

&lt;p&gt;In this case, logging in gives you a valid forms auth cookie, so your next request will pass authorization.&lt;/p&gt;

&lt;h2&gt;What about other validation scenarios?&lt;/h2&gt;

&lt;p&gt;If you want to do something different with validation in an ASP.NET Web API controller, usually the best approach is to create a custom Authorization Filter which derives from the base &lt;a href="http://msdn.microsoft.com/en-us/library/hh836085(v=vs.108).aspx"&gt;AuthorizationFilterAttribute&lt;/a&gt; and overrides the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.http.filters.authorizationfilterattribute.onauthorization(v=vs.108).aspx"&gt;OnAuthorization&lt;/a&gt; method. Here a few blog posts showing how to extend authentication in ASP.NET Web API:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.tugberkugurlu.com/archive/api-key-authorization-through-query-string-in-asp-net-web-api-authorizationfilterattribute"&gt;API Key Authorization Through Query String In ASP.NET Web API AuthorizationFilterAttribute&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.leastprivilege.com/ASPNETWebAPISecurity4ExamplesForVariousAuthenticationScenarios.aspx"&gt;ASP.NET WebAPI Security 4: Examples for various Authentication Scenarios&lt;/a&gt; (and Dominick Baier's other post on identity in ASP.NET Web API) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the client, it's up to you. You may want to show a login form in a desktop application, handle things programmatically when accessing the service via code, etc. You'll follow the same pattern, though - handle the HTTP 401 status code and login to the server, either by posting to a login action or following the service's documented login API.&lt;/p&gt;

&lt;h2&gt;The End... and Where To Next&lt;/h2&gt;

&lt;p&gt;That wraps up this series. Some ideas of where to go next:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The ASP.NET Web API content area at &lt;a href="http://asp.net/web-api"&gt;http://asp.net/web-api&lt;/a&gt; has a lot more information on ASP.NET Web API, and we'll be adding to it as more becomes available. For instance, see &lt;a href="http://www.asp.net/web-api/overview"&gt;Mike Wasson's tutorials&lt;/a&gt; which range from &lt;a href="http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api"&gt;Your First ASP.NET Web API&lt;/a&gt; to more advanced topics like &lt;a href="http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters"&gt;Media Formatters&lt;/a&gt; and&amp;#160; &lt;a href="http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver"&gt;Using the Web API Dependency Resolver&lt;/a&gt;. &lt;/li&gt;

  &lt;li&gt;There are several samples posted at &lt;a title="http://www.asp.net/web-api/samples" href="http://www.asp.net/web-api/samples"&gt;http://www.asp.net/web-api/samples&lt;/a&gt;, and a lot more listed in the &lt;a href="http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=Technology&amp;amp;f%5B0%5D.Value=ASP.NET%20Web%20API&amp;amp;f%5B0%5D.Text=ASP.NET%20Web%20API&amp;amp;sortBy=Date"&gt;MSDN Sample Gallery&lt;/a&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Henrik_Frystyk_Nielsen"&gt;Henrik F Nielsen (who knows quite a bit about HTTP)&lt;/a&gt; has written a lot of &lt;a href="http://blogs.msdn.com/b/henrikn/archive/tags/aspnetwebapi/"&gt;in-depth posts about some more advanced scenarios in ASP.NET Web API&lt;/a&gt;. &lt;/li&gt;

  &lt;li&gt;If you've got questions, the ASP.NET Web API product team are all on the &lt;a href="http://forums.asp.net/1246.aspx/1?ASP+NET+Web+API"&gt;Web API forum at forums.asp.net&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8361325" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=RUx_4-n7Pxc:Ggo4ZnxI1Tg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=RUx_4-n7Pxc:Ggo4ZnxI1Tg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=RUx_4-n7Pxc:Ggo4ZnxI1Tg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=RUx_4-n7Pxc:Ggo4ZnxI1Tg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=RUx_4-n7Pxc:Ggo4ZnxI1Tg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=RUx_4-n7Pxc:Ggo4ZnxI1Tg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=RUx_4-n7Pxc:Ggo4ZnxI1Tg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/RUx_4-n7Pxc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/WebAPI/default.aspx">WebAPI</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-6-authorization.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series Part 5: Custom Validation</title><link>http://feedproxy.google.com/~r/jongalloway/~3/azF4WHoB0Bg/asp-net-web-api-screencast-series-part-5-custom-validation.aspx</link><pubDate>Fri, 23 Mar 2012 22:51:24 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8361213</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8361213</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-5-custom-validation.aspx#comments</comments><description>&lt;p&gt;We're continuing a six part series on ASP.NET Web API that accompanies the getting started screencast series. This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;Part 1&lt;/a&gt; we looked at what ASP.NET Web API is, why you'd care, did the File / New Project thing, and did some basic HTTP testing using browser F12 developer tools.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx"&gt;Part 2&lt;/a&gt; we started to build up a sample that returns data from a repository in JSON format via GET methods.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx"&gt;Part 3&lt;/a&gt;, we modified data on the server using DELETE and POST methods.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx"&gt;Part 4&lt;/a&gt;, we extended on our simple querying methods form Part 2, adding in support for paging and querying.&lt;/p&gt;  &lt;p&gt;In Part 5, we'll add on support for Data Annotation based validation using an Action Filter.&lt;/p&gt; &lt;video height="525" width="644" controls src="http://content5.catalog.video.msn.com/e2/ds/e7bd5536-16ca-453a-8041-6ccf0e628406.mp4" preload="metadata"&gt;&lt;object id="SilverlightMediaPlayer" style="width:644px;height:525px;" autoupdate="true" data="data:application/x-silverlight-2," type="application/x-silverlight-2"&gt; 	&lt;param name="MinRuntimeVersion" value="2.0.31005.0" /&gt; 	&lt;param name="source" value="http://asp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002" /&gt; 	&lt;param name="InitParams" value="extendedfeatures=false,videoid=37167,videowidth=644,videoheight=525" /&gt; 	&lt;/object&gt;&lt;/video&gt;  &lt;h2&gt;&lt;/h2&gt;    &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/custom-validation"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;h2&gt;Adding Validation Rules using Data Annotations&lt;/h2&gt;  &lt;p&gt;To start with, we add some validation rules to our model class using &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; - &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.requiredattribute.aspx"&gt;Required&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.stringlengthattribute.aspx"&gt;StringLength&lt;/a&gt; in this case.&lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false;"&gt;[Required] 
public string Text { get; set; } 
 
[Required] 
[StringLength(10, ErrorMessage = &amp;quot;Author is too long! This was validated on the server.&amp;quot;)] 
public string Author { get; set; } 
 
[Required] 
public string Email { get; set; } &lt;/pre&gt;

&lt;h2&gt;Writing an Action Filter that Enforces Validation Rules&lt;/h2&gt;

&lt;p&gt;In ASP.NET MVC, that would be it - the validation rules are enforced in controller actions, and automatically passed along as HTML5 data- attributes where they're handled via unobtrusive jQuery validation in the browser. ASP.NET Web API doesn't directly enforce those validation rules without a little more work, though. I think that might be because handling validation errors in an HTTP API isn't something you'd want to do automatically. Who knows, maybe they'll add that in later just to make me look dumb(er). But for now, it takes a bit of work to enforce those validation rules.&lt;/p&gt;

&lt;p&gt;Fortunately, by a little more work I mean about 10-15 lines of code. It's easy to hook this kind of thing up using an &lt;a href="http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs"&gt;ASP.NET MVC action filter&lt;/a&gt;. Action filters are really powerful, as they allow you to modify &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspx"&gt;how controller actions work using the following methods&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;OnActionExecuting&lt;/strong&gt; – This method is called before a controller action is executed. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;OnActionExecuted&lt;/strong&gt; – This method is called after a controller action is executed. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;OnResultExecuting&lt;/strong&gt; – This method is called before a controller action result is executed. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;OnResultExecuted&lt;/strong&gt; – This method is called after a controller action result is executed. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can apply an action filter attribute on specific actions, on an entire controller class, or &lt;a href="http://msdn.microsoft.com/en-us/gg618496"&gt;globally&lt;/a&gt;. There are a few built-in action filters to handle common cases like custom authorization or error handling, and you can extend them if you need to handle a custom scenario.&lt;/p&gt;

&lt;p&gt;ASP.NET Web API uses that same extensibility model via &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.http.filters.filterattribute(v=vs.108).aspx"&gt;Filters&lt;/a&gt;. If you want ASP.NET Web API to do something that's not built in, the hook for that is very often to use an action filter. As with ASP.NET Action Filters, you can either extend on any of the in-built filters ( ResultLimit, AuthorizationFilter, ExceptionFilter) or write a custom ActionFilterAttribute. &lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;public class ValidationActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext context) 
    { 
        var modelState = context.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; 
                } 
            } 

            context.Response = new HttpResponseMessage&amp;lt;JsonValue&amp;gt;(errors, HttpStatusCode.BadRequest); 
        } 
    } 
}&lt;/pre&gt;

&lt;p&gt;This is an OnActionExecuting filter, so it executes before the Action. It takes in the context (note - this is a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.http.controllers.httpactioncontext(v=vs.108).aspx"&gt;System.Web.Http.Controllers.HttpActionContext&lt;/a&gt;, not an &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx"&gt;System.Web.HttpContext&lt;/a&gt;), which gives it access to ModelState as well as other contextual information about the request. It runs any custom logic, and has the option of directly returning the response - as it does in case validation fails.&lt;/p&gt;

&lt;p&gt;So, at a high level, we just need to check if the model fails validation, and if so, return an appropriate response.&lt;/p&gt;

&lt;h3&gt;1. Checking Data Annotation validation rules&lt;/h3&gt;

&lt;p&gt;As mentioned earlier in the series, ASP.NET Web API uses the same model binding system that's been in ASP.NET MVC for a while, so it already knows how to check validation rules from data annotations. That makes this step really easy - we just check the context.ModelState to see if it's valid. If it is, we're done - let the Action do its work and return the result. If it fails, go on to step 2.&lt;/p&gt;

&lt;h3&gt;2. Packaging up validation errors for the client&lt;/h3&gt;

&lt;p&gt;A single request can fail multiple validation rules, so to return useful information to the client we need to package up the error information. We could build up a structured, custom error results object, but we'd be serializing it to JSON when we were done, so why not just start there? ASP.NET Web API includes some very useful JSON classes, including &lt;a href="http://msdn.microsoft.com/en-us/library/system.json.jsonobject(v=vs.108).aspx"&gt;JsonObject&lt;/a&gt;. JsonObject allows us to work with a C# dynamic that will be serialized as a JSON object very easily.&lt;/p&gt;

&lt;h3&gt;3. Returning a useful error error response&lt;/h3&gt;

&lt;p&gt;Finally, when we're done wrapping up all the validation errors, we return a response to the client. We can use an HttpResponseMessage&amp;lt;JsonValue&amp;gt; to both return the results and set the HTTP Status Code (HTTP 400 Bad Request) in one line:&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;context.Response = new HttpResponseMessage&amp;lt;JsonValue&amp;gt;(errors, HttpStatusCode.BadRequest); &lt;/pre&gt;

&lt;p&gt;You'll remember from earlier in the series that HTTP Status Codes are very important to HTTP APIs, and that by always setting the appropriate status code our clients (be they JavaScript, .NET desktop clients, iOS devices, or aliens who natively speak HTTP) will be able to understand responses without reading a bunch of API documentation. If a client makes a bad request, we'll tell them it was a bad request, and send along validation errors in JSON format in case they want specifics.&lt;/p&gt;

&lt;h2&gt;Registering a Global Filter&lt;/h2&gt;

&lt;p&gt;As with ASP.NET MVC filters, ASP.NET Web API filters can be applied at whatever level of granularity you'd like - action, controller, or globally. In this case, we'd like the rules to be enforced on all actions in the application. We can do that by registering a global filter. That's a one-line change - we add a call in our Global.asax.cs Configure method to register the new filter:&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false; highlight: [3];"&gt;public static void Configure(HttpConfiguration config) 
{ 
    config.Filters.Add(new ValidationActionFilter()); 
 
    var kernel = new StandardKernel(); 
    kernel.Bind&amp;lt;ICommentRepository&amp;gt;().ToConstant(new InitialData()); 
    config.ServiceResolver.SetResolver( 
        t =&amp;gt; kernel.TryGet(t), 
        t =&amp;gt; kernel.GetAll(t)); 
} &lt;/pre&gt;

&lt;h2&gt;Handling Validation Responses in a JavaScript Client&lt;/h2&gt;

&lt;p&gt;In this sample, we're working with a JavaScript client. Just for the sake of &lt;a href="http://www.powderblueorbit.com/2wm3x36.gif"&gt;beating a dead horse&lt;/a&gt; a bit more, I'll remind you that JavaScript is a browser is just one possible client.&lt;/p&gt;

&lt;p&gt;To add handle validation failures, we need to include a case for HTTP Status Code 400 in our $.ajax() jQuery call.&lt;/p&gt;

&lt;pre class="brush: js; auto-links: false; highlight: [11];"&gt;$.ajax({ 
    url: '/api/comments', 
    cache: false, 
    type: 'POST', 
    data: json, 
    contentType: 'application/json; charset=utf-8', 
    statusCode: { 
        201 /*Created*/: function (data) { 
            viewModel.comments.push(data); 
        }, 
        400 /* BadRequest */: function (jqxhr) { 
            var validationResult = $.parseJSON(jqxhr.responseText); 
            $.validator.unobtrusive.revalidate(form, validationResult); 
        } 
    } 
}); &lt;/pre&gt;

&lt;h2&gt;Break the rules? Talk to the HTTP 400.&lt;/h2&gt;

&lt;p&gt;So here's how this looks in action - filling out the form with an Author name that exceeds 10 characters now gets an HTTP 400 response.&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-03-23 15h40_12" href="http://www.flickr.com/photos/36836555@N00/6863439238/"&gt;&lt;img border="0" alt="2012-03-23 15h40_12" src="http://static.flickr.com/7187/6863439238_3f92c714fb_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The error message shown above - &amp;quot;Author is too long! This was validated on the server.&amp;quot; - is perhaps a little too smug, but is derived from the JSON error information in the request body:&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-03-23 15h42_51" href="http://www.flickr.com/photos/36836555@N00/7009557231/"&gt;&lt;img border="0" alt="2012-03-23 15h42_51" src="http://static.flickr.com/7218/7009557231_1a5ef0d743_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Onward!&lt;/h2&gt;

&lt;p&gt;That wraps up our look at supporting Data Annotation based validation using an Action Filter. In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-6-authorization.aspx"&gt;Part 6&lt;/a&gt;, we'll finish off the series with a look at Authorization using the built-in Authorize filter.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8361213" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=azF4WHoB0Bg:_ON4LHmklJE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=azF4WHoB0Bg:_ON4LHmklJE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=azF4WHoB0Bg:_ON4LHmklJE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=azF4WHoB0Bg:_ON4LHmklJE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=azF4WHoB0Bg:_ON4LHmklJE:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=azF4WHoB0Bg:_ON4LHmklJE:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=azF4WHoB0Bg:_ON4LHmklJE:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/azF4WHoB0Bg" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/WebAPI/default.aspx">WebAPI</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-5-custom-validation.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series Part 4: Paging and Querying</title><link>http://feedproxy.google.com/~r/jongalloway/~3/y8fLqQnsUiI/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx</link><pubDate>Fri, 16 Mar 2012 19:27:54 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8350910</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8350910</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx#comments</comments><description>&lt;p&gt;We're continuing a six part series on ASP.NET Web API that accompanies the getting started screencast series. This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;Part 1&lt;/a&gt; we looked at what ASP.NET Web API is, why you'd care, did the File / New Project thing, and did some basic HTTP testing using browser F12 developer tools.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx"&gt;Part 2&lt;/a&gt; we started to build up a sample that returns data from a repository in JSON format via GET methods.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx"&gt;Part 3&lt;/a&gt;, we modified data on the server using DELETE and POST methods.&lt;/p&gt;  &lt;p&gt;In Part 4, we'll extend on our simple querying methods form Part 2, adding in support for paging and querying.&lt;/p&gt; &lt;video height="525" width="644&amp;quot;" controls src="http://content5.catalog.video.msn.com/e2/ds/b37e11b4-6ad0-4875-9851-218384366132.mp4"&gt;&lt;object id="SilverlightMediaPlayer" style="width:644px;height:525px;" autoupdate="true" data="data:application/x-silverlight-2," type="application/x-silverlight-2"&gt; 	&lt;param name="MinRuntimeVersion" value="2.0.31005.0" /&gt; 	&lt;param name="source" value="http://asp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002" /&gt; 	&lt;param name="InitParams" value="extendedfeatures=false,videoid=37166,videowidth=644,videoheight=525" /&gt; 	&lt;/object&gt;&lt;/video&gt;  &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/paging-and-querying"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;p&gt;This part shows two approaches to querying data (paging really just being a specific querying case) - you can do it yourself using parameters passed in via querystring (as well as headers, other route parameters, cookies, etc.). You're welcome to do that if you'd like.&lt;/p&gt;  &lt;p&gt;What I think is more interesting here is that Web API &lt;strong&gt;actions that return IQueryable automatically support OData query syntax&lt;/strong&gt;, making it really easy to support some common query use cases like paging and filtering. A few important things to note:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;This is &lt;strong&gt;just support for OData query syntax - you're not getting back data in OData format&lt;/strong&gt;. The screencast demonstrates this by showing the GET methods are continuing to return the same JSON they did previously. So you don't have to &amp;quot;buy in&amp;quot; to the whole OData thing, you're just able to use the query syntax if you'd like. &lt;/li&gt;    &lt;li&gt;This isn't full OData query support - &lt;a href="http://www.odata.org/developers/protocols/uri-conventions#QueryStringOptions"&gt;full OData query syntax includes a lot of operations and features&lt;/a&gt; - but it is a pretty good subset: filter, orderby, skip, and top. &lt;/li&gt;    &lt;li&gt;All you have to do to enable this OData query syntax is return an IQueryable rather than an IEnumerable. Often, that could be as simple as using the AsQueryable() extension method on your IEnumerable. &lt;/li&gt;    &lt;li&gt;Query composition support lets you layer queries intelligently. If, for instance, you had an action that showed products by category using a query in your repository, you could also support paging on top of that. The result is an expression tree that's evaluated on-demand and includes both the Web API query and the underlying query. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So with all those bullet points and big words, you'd think this would be hard to hook up. Nope, all I did was change the return type from IEnumerable&amp;lt;Comment&amp;gt; to IQueryable&amp;lt;Comment&amp;gt; and convert the Get() method's IEnumerable result using the .AsQueryable() extension method.&lt;/p&gt;  &lt;pre class="brush: js; auto-links: false;"&gt;public IQueryable&amp;lt;Comment&amp;gt; GetComments() 
{ 
    return repository.Get().AsQueryable(); 
} &lt;/pre&gt;

&lt;p&gt;You still need to &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;build up the query to provide the $top and $skip on the client&lt;/a&gt;, but you'd need to do that regardless. Here's how that looks:&lt;/p&gt;

&lt;pre class="brush: js; auto-links: false;"&gt;$(function () { 
    //--------------------------------------------------------- 
    // Using Queryable to page 
    //--------------------------------------------------------- 
    $(&amp;quot;#getCommentsQueryable&amp;quot;).click(function () { 
        viewModel.comments([]); 
 
        var pageSize = $('#pageSize').val(); 
        var pageIndex = $('#pageIndex').val(); 
 
        var url = &amp;quot;/api/comments?$top=&amp;quot; + pageSize + '&amp;amp;$skip=' + (pageIndex * pageSize); 
 
        $.getJSON(url, function (data) { 
            // Update the Knockout model (and thus the UI) with the comments received back  
            // from the Web API call. 
            viewModel.comments(data); 
        }); 
 
        return false; 
    }); 
});&lt;/pre&gt;

&lt;p&gt;And the neat thing is that - without any modification to our server-side code - we can modify the above jQuery call to request the comments be sorted by author:&lt;/p&gt;

&lt;pre class="brush: js; auto-links: false;"&gt;$(function () { 
    //--------------------------------------------------------- 
    // Using Queryable to page 
    //--------------------------------------------------------- 
    $(&amp;quot;#getCommentsQueryable&amp;quot;).click(function () { 
        viewModel.comments([]); 
 
        var pageSize = $('#pageSize').val(); 
        var pageIndex = $('#pageIndex').val(); 
 
        var url = &amp;quot;/api/comments?$top=&amp;quot; + pageSize + '&amp;amp;$skip=' + (pageIndex * pageSize) + '&amp;amp;$orderby=Author'; 
 
        $.getJSON(url, function (data) { 
            // Update the Knockout model (and thus the UI) with the comments received back  
            // from the Web API call. 
            viewModel.comments(data); 
        }); 
 
        return false; 
    }); 
});&lt;/pre&gt;

&lt;p&gt;So if you want to make use of OData query syntax, you can. If you don't like it, you're free to hook up your filtering and paging however you think is best. Neat.&lt;/p&gt;

&lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/23/asp-net-web-api-screencast-series-part-5-custom-validation.aspx"&gt;Part 5&lt;/a&gt;, we'll add on support for Data Annotation based validation using an Action Filter.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8350910" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=y8fLqQnsUiI:6MtOEeQdxww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=y8fLqQnsUiI:6MtOEeQdxww:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=y8fLqQnsUiI:6MtOEeQdxww:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=y8fLqQnsUiI:6MtOEeQdxww:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=y8fLqQnsUiI:6MtOEeQdxww:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=y8fLqQnsUiI:6MtOEeQdxww:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=y8fLqQnsUiI:6MtOEeQdxww:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/y8fLqQnsUiI" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/WebAPI/default.aspx">WebAPI</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series Part 3: Delete and Update</title><link>http://feedproxy.google.com/~r/jongalloway/~3/s3gSvvXpXUo/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx</link><pubDate>Fri, 16 Mar 2012 19:01:42 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8350855</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8350855</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx#comments</comments><description>&lt;p&gt;We're continuing a six part series on ASP.NET Web API that accompanies the getting started screencast series. This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;Part 1&lt;/a&gt; we looked at what ASP.NET Web API is, why you'd care, did the File / New Project thing, and did some basic HTTP testing using browser F12 developer tools.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx"&gt;Part 2&lt;/a&gt; we started to build up a sample that returns data from a repository in JSON format via GET methods.&lt;/p&gt;  &lt;p&gt;In Part 3, we'll start to modify data on the server using DELETE and POST methods.&lt;/p&gt; &lt;video height="525" width="644&amp;quot;" controls src="http://content5.catalog.video.msn.com/e2/ds/3d937a28-8099-421d-abe3-995de4f6e3ae.mp4"&gt;&lt;object id="SilverlightMediaPlayer" style="width:644px;height:525px;" autoupdate="true" data="data:application/x-silverlight-2," type="application/x-silverlight-2"&gt; &lt;param name="MinRuntimeVersion" value="2.0.31005.0" /&gt; &lt;param name="source" value="http://www.aasp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002" /&gt; &lt;param name="InitParams" value="extendedfeatures=false,videoid=37165,videowidth=644,videoheight=525" /&gt; &lt;/object&gt;&lt;/video&gt;  &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/delete-and-update"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;p&gt;So far we've been looking at GET requests, and the difference between standard browsing in a web browser and navigating an HTTP API isn't quite as clear. Delete is where the difference becomes more obvious. With a &amp;quot;traditional&amp;quot; web page, to delete something'd probably have a form that POSTs a request back to a controller that needs to know that it's really supposed to be deleting something even though POST was really designed to create things, so it does the work and then returns some HTML back to the client that says whether or not the delete succeeded. There's a good amount of plumbing involved in communicating between client and server. &lt;/p&gt;  &lt;p&gt;That gets a lot easier when we just work with the standard HTTP DELETE verb. Here's how the server side code works:&lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false;"&gt;public Comment DeleteComment(int id)  
{ 
    Comment comment; 
    if (!repository.TryGet(id, out comment)) 
        throw new HttpResponseException(HttpStatusCode.NotFound); 
    repository.Delete(id); 
    return comment; 
} &lt;/pre&gt;

&lt;p&gt;If you look back at the GET /api/comments code in Part 2, you'll see that they start the exact same because the use cases are kind of similar - we're looking up an item by id and either displaying it or deleting it. So the only difference is that this method deletes the comment once it finds it. We don't need to do anything special to handle cases where the id isn't found, as the same HTTP 404 handling works fine here, too.&lt;/p&gt;

&lt;p&gt;Pretty much all &amp;quot;traditional&amp;quot; browsing uses just two HTTP verbs: GET and POST, so you might not be all that used to DELETE requests and think they're hard. Not so! Here's the jQuery method that calls the /api/comments with the DELETE verb:&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;$(function() { 
    $(&amp;quot;a.delete&amp;quot;).live('click', function () { 
        var id = $(this).data('comment-id'); 
 
        $.ajax({ 
            url: &amp;quot;/api/comments/&amp;quot; + id, 
            type: 'DELETE', 
            cache: false, 
            statusCode: { 
                200: function(data) { 
                    viewModel.comments.remove( 
                        function(comment) {  
                            return comment.ID == data.ID;  
                        } 
                    ); 
                } 
            } 
        }); 
 
        return false; 
    }); 
});&lt;/pre&gt;

&lt;p&gt;So in order to use the DELETE verb instead of GET, we're just using $.ajax() and setting the type to DELETE. Not hard.&lt;/p&gt;

&lt;p&gt;But what's that statusCode business? Well, an HTTP status code of 200 is an OK response. Unless our Web API method sets another status (such as by throwing the Not Found exception we saw earlier), the default response status code is HTTP 200 - OK. That makes the jQuery code pretty simple - it calls the Delete action, and if it gets back an HTTP 200, the server-side delete was successful so the comment can be deleted.&lt;/p&gt;

&lt;p&gt;Adding a new comment uses the POST verb. It starts out looking like an MVC controller action, using model binding to get the new comment from JSON data into a c# model object to add to repository, but there are some interesting differences.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;public HttpResponseMessage&amp;lt;Comment&amp;gt; PostComment(Comment comment)  
{ 
    comment = repository.Add(comment); 
    var response = new HttpResponseMessage&amp;lt;Comment&amp;gt;(comment, HttpStatusCode.Created); 
    response.Headers.Location = new Uri(Request.RequestUri, &amp;quot;/api/comments/&amp;quot; + comment.ID.ToString()); 
    return response; 
} &lt;/pre&gt;

&lt;p&gt;First off, the POST method is returning an HttpResponseMessage&amp;lt;Comment&amp;gt;. In the GET methods earlier, we were just returning a JSON payload with an HTTP 200 OK, so we could just return the&amp;#160; model object and Web API would wrap it up in an HttpResponseMessage with that HTTP 200 for us (much as ASP.NET MVC controller actions can return strings, and they'll be automatically wrapped in a ContentResult). When we're creating a new comment, though, we want to follow standard REST practices and return the URL that points to the newly created comment in the Location header, and we can do that by explicitly creating that HttpResposeMessage and then setting the header information.&lt;/p&gt;

&lt;p&gt;And here's a key point - by using HTTP standard status codes and headers, our response payload doesn't need to explain any context - the client can see from the status code that the POST succeeded, the location header tells it where to get it, and all it needs in the JSON payload is the actual content. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: This is a simplified sample. Among other things, you'll need to consider security and authorization in your Web API's, and especially in methods that allow creating or deleting data. We'll look at authorization in Part 6. As for security, you'll want to consider things like mass assignment if binding directly to model objects, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-4-paging-and-querying.aspx"&gt;Part 4&lt;/a&gt;, we'll extend on our simple querying methods form Part 2, adding in support for paging and querying.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8350855" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=s3gSvvXpXUo:jrNyoJzf7qY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=s3gSvvXpXUo:jrNyoJzf7qY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=s3gSvvXpXUo:jrNyoJzf7qY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=s3gSvvXpXUo:jrNyoJzf7qY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=s3gSvvXpXUo:jrNyoJzf7qY:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=s3gSvvXpXUo:jrNyoJzf7qY:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=s3gSvvXpXUo:jrNyoJzf7qY:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/s3gSvvXpXUo" height="1" width="1"/&gt;</description><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-3-delete-and-update.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series Part 2: Getting Data</title><link>http://feedproxy.google.com/~r/jongalloway/~3/b6mRuAQAzIY/asp-net-web-api-screencast-series-part-2-getting-data.aspx</link><pubDate>Fri, 16 Mar 2012 18:54:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8350836</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8350836</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx#comments</comments><description>&lt;p&gt;We're continuing a six part series on ASP.NET Web API that accompanies the getting started screencast series. This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos" mce_href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx" mce_href="http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx"&gt;Part 1&lt;/a&gt; we looked at what ASP.NET Web API is, why you'd care, did the File / New Project thing, and did some basic HTTP testing using browser F12 developer tools.&lt;/p&gt;  &lt;p&gt;This second screencast starts to build out the Comments example - a JSON API that's accessed via jQuery. This sample uses a simple in-memory repository. At this early stage, the GET /api/values/ just returns an IEnumerable&amp;lt;Comment&amp;gt;. In part 4 we'll add on paging and filtering, and it gets more interesting.&lt;/p&gt; &lt;video mce_src="http://content4.catalog.video.msn.com/e2/ds/8dc2254f-fde6-4589-833c-b834d10af3a2.mp4" height="525" width="644" controls="" src="http://content4.catalog.video.msn.com/e2/ds/8dc2254f-fde6-4589-833c-b834d10af3a2.mp4" preload="metadata"&gt;&lt;object style="width: 644px; height: 525px;" id="SilverlightMediaPlayer" data="data:application/x-silverlight-2," type="application/x-silverlight-2" autoupdate="true"&gt; 	&lt;param name="MinRuntimeVersion" value="2.0.31005.0"&gt; 	&lt;param name="source" value="http://asp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002"&gt; 	&lt;param name="InitParams" value="extendedfeatures=false,videoid=37164,videowidth=644,videoheight=525"&gt; 	&lt;/object&gt;&lt;/video&gt;&amp;#160;&amp;#160;&amp;#160; &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/getting-data"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;p&gt;The get by id (e.g. GET /api/values/5) case is a little more interesting. The method just returns a Comment if the Comment ID is valid, but if it's not found we throw an HttpResponseException with the correct HTTP status code (HTTP 404 Not Found). This is an important thing to get - HTTP defines common response status codes, so there's no need to implement any custom messaging here - we tell the requestor that the resource the requested wasn't there.&amp;#160; &lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false;"&gt;public Comment GetComment(int id) 
{ 
    Comment comment; 
    if (!repository.TryGet(id, out comment)) 
        throw new HttpResponseException(HttpStatusCode.NotFound); 
    return comment; 
} &lt;/pre&gt;

&lt;p&gt;This is great because it's standard, and any client should know how to handle it. There's no need to invent custom messaging here, and we can talk to any client that understands HTTP - not just jQuery, and not just browsers.&lt;/p&gt;

&lt;p&gt;But it's crazy easy to &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=1335708962" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=1335708962"&gt;consume an HTTP API that returns JSON via jQuery&lt;/a&gt;. The example uses Knockout to bind the JSON values to HTML elements, but the thing to notice is that calling into this /api/coments is really simple, and the return from the $.get() method is just JSON data, which is really easy to work with in JavaScript (since JSON stands for JavaScript Object Notation and is the native serialization format in Javascript). &lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;$(function() { 
    $(&amp;quot;#getComments&amp;quot;).click(function () { 
        // We're using a Knockout model. This clears out the existing comments. 
        viewModel.comments([]); 
 
        $.get('/api/comments', function (data) { 
            // Update the Knockout model (and thus the UI) with the comments received back  
            // from the Web API call. 
            viewModel.comments(data); 
        }); 
 
    }); 
});&lt;/pre&gt;

&lt;p&gt;That's it! Easy, huh? In Part 3, we'll start modifying data on the server using POST and DELETE.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8350836" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=b6mRuAQAzIY:v0Ck_4q_OlU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=b6mRuAQAzIY:v0Ck_4q_OlU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=b6mRuAQAzIY:v0Ck_4q_OlU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=b6mRuAQAzIY:v0Ck_4q_OlU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=b6mRuAQAzIY:v0Ck_4q_OlU:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=b6mRuAQAzIY:v0Ck_4q_OlU:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=b6mRuAQAzIY:v0Ck_4q_OlU:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/b6mRuAQAzIY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/WebAPI/default.aspx">WebAPI</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-part-2-getting-data.aspx</feedburner:origLink></item><item><title>ASP.NET Web API - Screencast series with downloadable sample code - Part 1</title><link>http://feedproxy.google.com/~r/jongalloway/~3/GS66i7GAo-U/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx</link><pubDate>Fri, 16 Mar 2012 18:46:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8350817</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>6</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8350817</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx#comments</comments><description>&lt;p&gt;There's a lot of great ASP.NET Web API content on the ASP.NET website at &lt;a href="http://asp.net/web-api" mce_href="http://asp.net/web-api"&gt;http://asp.net/web-api&lt;/a&gt;. I mentioned my screencast series in original announcement post, but we've since added the sample code so I thought it was worth pointing the series out specifically. &lt;/p&gt;  &lt;p&gt;This is an introductory screencast series that walks through from File / New Project to some more advanced scenarios like Custom Validation and Authorization. The screencast &lt;a href="http://www.asp.net/web-api/videos" mce_href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are all short (3-5 minutes) and the &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7"&gt;sample code&lt;/a&gt; for the series is both available for &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/file/50314/5/ASP.NET%20Web%20API%20JavaScript%20Scenarios%20-%20Comments.zip"&gt;download&lt;/a&gt; and &lt;a href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761" mce_href="http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?fileId=50314&amp;amp;pathId=352866761"&gt;browsable&lt;/a&gt; online. I did the screencasts, but the samples were written by the ASP.NET Web API team.&lt;/p&gt;  &lt;p&gt;So - let's watch them together! Grab some popcorn and pay attention, because these are short. After each video, I'll talk about what I thought was important. I'm embedding the videos using HTML5 (MP4) with Silverlight fallback, but if something goes wrong or your browser / device / whatever doesn't support them, I'll include the link to where the &lt;a href="http://www.asp.net/web-api/videos" mce_href="http://www.asp.net/web-api/videos"&gt;videos&lt;/a&gt; are more professionally hosted on the ASP.NET site. Note also if you're following along with the samples that, since Part 1 just looks at the File / New Project step, the screencast part numbers are one ahead of the sample part numbers - so screencast 4 matches with sample code demo 3. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Note: I started this as one long post for all 6 parts, but as it grew over 2000 words I figured it'd be better to break it up.&lt;/em&gt;&lt;/p&gt;  &lt;h2&gt;Part 1: Your First Web API&lt;/h2&gt; &lt;video mce_src="http://content4.catalog.video.msn.com/e2/ds/5f5b86eb-3a48-4cca-9707-66aa1e82c49b.mp4" height="525" width="644" controls="" src="http://content4.catalog.video.msn.com/e2/ds/5f5b86eb-3a48-4cca-9707-66aa1e82c49b.mp4" preload="metadata"&gt;&lt;object style="width: 644px; height: 525px;" id="SilverlightMediaPlayer" data="data:application/x-silverlight-2," type="application/x-silverlight-2" autoupdate="true"&gt; 	&lt;param name="MinRuntimeVersion" value="2.0.31005.0"&gt; 	&lt;param name="source" value="http://asp.net/ClientBin/mediaplayer/MSCommunities.MediaPlayer.xap?cdn_id=2012-03-01-002"&gt; 	&lt;param name="InitParams" value="extendedfeatures=false,videoid=37163,videowidth=644,videoheight=525"&gt; 	&lt;/object&gt;&lt;/video&gt;  &lt;p&gt;[&lt;a href="http://www.asp.net/web-api/videos/getting-started/your-first-web-api"&gt;Video and code on the ASP.NET site&lt;/a&gt;]&lt;/p&gt;  &lt;p&gt;This screencast starts with an overview of why you'd want to use ASP.NET Web API:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Reach more clients (thinking beyond the browser to mobile clients, other applications, etc.) &lt;/li&gt;    &lt;li&gt;Scale (who doesn't love the cloud?!) &lt;/li&gt;    &lt;li&gt;Embrace HTTP (a focus on HTTP both on client and server really simplifies and focuses service interactions) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Next, I start a new ASP.NET Web API application and show some of the basics of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.http.apicontroller(v=vs.108).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.web.http.apicontroller(v=vs.108).aspx"&gt;ApiController&lt;/a&gt;. We don't write any new code in this first step, just look at the example controller that's created by File / New Project.&lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false;"&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http;

namespace NewProject_Mvc4BetaWebApi.Controllers
{
    public class ValuesController : ApiController
    {
        // GET /api/values
        public IEnumerable&amp;lt;string&amp;gt; Get()
        {
            return new string[] { &amp;quot;value1&amp;quot;, &amp;quot;value2&amp;quot; };
        }

        // GET /api/values/5
        public string Get(int id)
        {
            return &amp;quot;value&amp;quot;;
        }

        // POST /api/values
        public void Post(string value)
        {
        }

        // PUT /api/values/5
        public void Put(int id, string value)
        {
        }

        // DELETE /api/values/5
        public void Delete(int id)
        {
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Finally, we walk through testing the output of this API controller using browser tools. There are several ways you can test API output, including Fiddler (as &lt;a href="http://www.hanselman.com/blog/OneASPNETMakingJSONWebAPIsWithASPNETMVC4BetaAndASPNETWebAPI.aspx" mce_href="http://www.hanselman.com/blog/OneASPNETMakingJSONWebAPIsWithASPNETMVC4BetaAndASPNETWebAPI.aspx"&gt;described by Scott Hanselman in this post&lt;/a&gt;) and built-in developer tools available in all modern browsers. For simplicity I used Internet Explorer 9 F12 developer tools, but you're of course welcome to use whatever you'd like.&lt;/p&gt;

&lt;p&gt;A few important things to note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This class derives from an ApiController base class, not the standard ASP.NET MVC Controller base class. They're similar in places where API's and HTML returning controller uses are similar, and different where API and HTML use differ. &lt;/li&gt;

  &lt;li&gt;A good example of where those things are different is in the routing conventions. In an HTTP controller, there's no need for an &amp;quot;action&amp;quot; to be specified, since the HTTP verbs are the actions. We don't need to do anything to map verbs to actions; when a request comes in to /api/values/5 with the DELETE HTTP verb, it'll automatically be handled by the Delete method in an ApiController. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The comments above the API methods show sample URL's and HTTP verbs, so we can test out the first two GET methods by browsing to the site in IE9, hitting F12 to bring up the tools, and entering /api/values in the URL:&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-03-12 16h02_28" href="http://www.flickr.com/photos/36836555@N00/6831430564/" mce_href="http://www.flickr.com/photos/36836555@N00/6831430564/"&gt;&lt;img border="0" alt="2012-03-12 16h02_28" src="http://farm8.static.flickr.com/7182/6831430564_da1b835e51_b.jpg" mce_src="http://farm8.static.flickr.com/7182/6831430564_da1b835e51_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That sample action returns a list of values. To get just one value back, we'd browse to /values/5:&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-03-12 16h04_22" href="http://www.flickr.com/photos/36836555@N00/6977558825/" mce_href="http://www.flickr.com/photos/36836555@N00/6977558825/"&gt;&lt;img border="0" alt="2012-03-12 16h04_22" src="http://farm8.static.flickr.com/7178/6977558825_df55d8850d_b.jpg" mce_src="http://farm8.static.flickr.com/7178/6977558825_df55d8850d_b.jpg" /&gt;&lt;/a&gt; 

  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;That's it for Part 1. In &lt;a href="http://feedproxy.google.com/~r/jongalloway/~3/b6mRuAQAzIY/asp-net-web-api-screencast-series-part-2-getting-data.aspx" mce_href="http://feedproxy.google.com/~r/jongalloway/~3/b6mRuAQAzIY/asp-net-web-api-screencast-series-part-2-getting-data.aspx"&gt;Part 2&lt;/a&gt; we'll look at getting data (beyond hardcoded strings) and start building out a sample application.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8350817" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=GS66i7GAo-U:Q25Asg5I9lk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=GS66i7GAo-U:Q25Asg5I9lk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=GS66i7GAo-U:Q25Asg5I9lk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=GS66i7GAo-U:Q25Asg5I9lk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=GS66i7GAo-U:Q25Asg5I9lk:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=GS66i7GAo-U:Q25Asg5I9lk:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=GS66i7GAo-U:Q25Asg5I9lk:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/GS66i7GAo-U" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/WebAPI/default.aspx">WebAPI</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/03/16/asp-net-web-api-screencast-series-with-downloadable-sample-code-part-1.aspx</feedburner:origLink></item><item><title>ZenBook UX31E - Follow up</title><link>http://feedproxy.google.com/~r/jongalloway/~3/-zjDiyR1_oY/zenbook-ux31e-follow-up.aspx</link><pubDate>Wed, 29 Feb 2012 01:43:46 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8318847</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8318847</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/02/28/zenbook-ux31e-follow-up.aspx#comments</comments><description>&lt;p&gt;I previously wrote about some initial impressions of a &lt;a href="http://www.amazon.com/gp/product/B005SY32Q2?ie=UTF8&amp;amp;amp;tag=jongall-20&amp;amp;amp;linkCode=shr&amp;amp;amp;camp=213733&amp;amp;amp;creative=393177&amp;amp;amp;creativeASIN=B005SY32Q2&amp;amp;amp;ref_=sr_1_1&amp;amp;amp;s=electronics&amp;amp;amp;qid=1327740305&amp;amp;amp;sr=1-1"&gt;ZenBook UX31E&lt;/a&gt; I've been reviewing. I've been using it heavily since then and wanted to follow up on how it's been working for me.&lt;/p&gt;  &lt;h3&gt;As A Work / Development Machine&lt;/h3&gt;  &lt;p&gt;When I'm working during the day, I usually have both a multi-monitor desktop computer and one or more laptops running. I usually have 1-2 Office documents open, 2-3 copies of Visual Studio 2010, Audacity, and several dozen tabs open in Chrome. I bounce back and forth between my desktop and laptop throughout the day. &lt;/p&gt;  &lt;p&gt;Evenings / nights / weekends I'm often doing some sort of hacking for fun, with podcast editing in the background - 2-3 copies of Visual Studio, Audacity, dozens of browser tabs. So, pretty heavy use most of the day.&lt;/p&gt;  &lt;p&gt;This thing holds up. It's not just a cute, convenient machine, it's good enough that it's been my primary dev and work machine since I got it over a month ago. I've kept it on my desk, right next to my super-beefy Lenovo W520, so that if it every slowed me down I'd just hop over to the Lenovo. That hasn't happened, which surprises me as much as it may surprise you.This thing is really snappy as a dev machine. I've been doing web development (including ASP.NET 4 Beta) as well as Windows Phone and WPF work. It really holds up.&lt;/p&gt;  &lt;p&gt;People have commented on my previous post that this machine's got to be underpowered because it's only got 4GB RAM, non-upgradable. I haven't found that to be an issue. The stats and overall performance on this machine are pretty decent overall:&lt;/p&gt;  &lt;p&gt;&lt;a title="Zenbook Windows Experience" href="http://www.flickr.com/photos/36836555@N00/6939462561/"&gt;&lt;img border="0" alt="Zenbook Windows Experience" src="http://farm8.static.flickr.com/7039/6939462561_29da5a45b3.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Numbers and specs are fine, but what's really important for me is how it handles in everyday use. As I've said, &lt;strong&gt;I've been using this laptop a lot over the past month, and I've found it to be more than up to the task.&lt;/strong&gt; Just to see if I've been subconsciously taking it easy on this thing, I just loaded up:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Two projects in Visual Studio 2010 (one WPF, one ASP.NET MVC 4 Beta) &lt;/li&gt;    &lt;li&gt;Windows Phone Emulator &lt;/li&gt;    &lt;li&gt;Twenty odd tabs in Chrome &lt;/li&gt;    &lt;li&gt;A few tabs in IE9 &lt;/li&gt;    &lt;li&gt;Seesmic Desktop 2 (Silverlight) with lots of plugins and columns &lt;/li&gt;    &lt;li&gt;Windows Live Writer &lt;/li&gt;    &lt;li&gt;Skype &lt;/li&gt;    &lt;li&gt;PowerShell console window &lt;/li&gt;    &lt;li&gt;VLC (playing a 1 hour MP3) &lt;/li&gt;    &lt;li&gt;Audacity (editing a 1 hour audio file) &lt;/li&gt;    &lt;li&gt;PowerPoint 2010 (40 slide deck with a pretty good amount of images) &lt;/li&gt;    &lt;li&gt;Windows Live Writer &lt;/li&gt;    &lt;li&gt;Notepad++ (a few tabs open) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I've also got some standard background stuff running - Microsoft Security Essentials, Mesh, pretty much all the Asus stuff that came pre-installed.&lt;/p&gt;  &lt;p&gt;And all of those apps are running smoothly. No lags, quick compiles, etc. It's responsive.&lt;/p&gt;  &lt;p&gt;So now I was curious as to what would cause things to drag noticeably. I decided to leave all the above running and load up Inkscape, then create tiled clones until it was taking nearly 1GB memory and saturating one core (each clock image below has a lot of vector data). That finally slowed things down a bit.&lt;/p&gt;  &lt;p&gt;&lt;a title="Cloned Tile Explosion" href="http://www.flickr.com/photos/36836555@N00/6793362060/"&gt;&lt;img border="0" alt="Cloned Tile Explosion" src="http://farm8.static.flickr.com/7064/6793362060_342dda02a3_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The point is that, for just about any realistic day to day use, this thing work great. I really had to go out of my way to get things to slow down. If you really need workstation performance, you're probably not shopping for an ultrabook. &lt;strong&gt;I said in my previous introductory review that this UX31 was challenging my preconceptions about the performance I could expect out of a small form factor laptop, and that's continued to hold true over the past month. I'm convinced.&lt;/strong&gt;&lt;/p&gt;  &lt;h2&gt;As a Technical Presentation Machine&lt;/h2&gt;  &lt;p&gt;This past month at TechReady, I presented a 75 minute talk on Mobile Development with ASP.NET MVC 4 to 120 people. It was a standard conference presentation: big stage, slides and demonstrations projected on a big screen, butterflies in stomach. I had mobile emulators running, PowerPoint going, and wrote a lot of demo code on the fly. &lt;/p&gt;  &lt;p&gt;This, for me, is the biggest stress test for a laptop. I'm usually pretty easy going, but when I'm speaking I get really sensitive to the slightest delays or difficulties from my laptop. I get mad. If this laptop was going to disappoint me, this would have been the time.&lt;/p&gt;  &lt;p&gt;I did all my preparation on the Zenbook, but had all the code set up on my humongous Lenovo W520 and was ready to bail out at any time. I wanted to present on this laptop, but I wasn't going to go with it if I thought I'd likely hit problems. No problems during my preparation. I took both laptops to the talk, just in case.&lt;/p&gt;  &lt;p&gt;Everything went fine - all my demos were fast.&lt;/p&gt;  &lt;p&gt;No problems with user input, either. When I'm presenting, I'm rushed and nervous and usually struggle with typos and trackpad foibles a lot more than in normal daily use. Not only didn't I have problems, I the keyboard worked better for me than on other laptops I've used in the past.&lt;/p&gt;  &lt;p&gt;Everything went fine when I hooked it up to the projector. That wasn't by accident - the great video support was one of the reasons I'd requested the Zenbook UX31, as it supports resolution up to 1600x900 (best resolution of any Ultrabook, including the MacBook Air). There are two dongles included for both ethernet and standard SVGA, and they worked just fine.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://zenbook.asus.com/imgs/prod.acc-3.png" /&gt;&lt;/p&gt;  &lt;h2&gt;As A Casual &amp;quot;Couch&amp;quot; Machine&lt;/h2&gt;  &lt;p&gt;I spend a lot of my off hours on a laptop. I'll be sitting on the couch with my wife and kids, pretending to watch movies or TV shows, but really just surfing or coding or whatever. That used to get me in trouble because I was very clearly not spending quality time with the family - as if watching TV together was quality time. But I digress.&lt;/p&gt;  &lt;p&gt;Things lightened up as the rest of the family got tablets and Kindle Fires and other smart devices. But still, for some reason, having a giant laptop wasn't considered as socially acceptable as browsing Facebook on a discreet little tablet. Fortunately, this tiny little laptop seems to be a lot more socially acceptable. It fits in better with cute little devices. When I'm using it, people assume I'm doing light, happy, frivolous things (even if it's not the case).&lt;/p&gt;  &lt;p&gt;I know this seems like a fluffy, non-technical thing to write in a laptop review, but it really is nice. I don't feel any social awkwardness using this on the couch or whatever. It looks like a casual device, even though I don't use it that way at all. &lt;/p&gt;  &lt;h2&gt;Travel / Mobile&lt;/h2&gt;  &lt;p&gt;This is pretty obvious, but of course this thing travels very well. It's small and lightweight, so it's easy to carry around. It's easy to take out on an airplane and just put in the seat pocket in front of me when I'm not using it. The battery easily lasts 4-6 hours, much longer in sleep mode. The charger and video/ethernet dongles are really small and travel well, too. Oh, and it feels solid enough that I don't worry about is as much as I would with a conventional laptop.&lt;/p&gt;  &lt;h2&gt;Other good features&lt;/h2&gt;  &lt;h3&gt;Speakers&lt;/h3&gt;  &lt;p&gt;The sound on this thing is great. It's better than any other laptop I've used. I use this laptop as a boombox while I'm jogging on the treadmill. The sound isn't just loud, it's substantial, and it's rich. I've shown it off with electronic music and classical music, and everyone I've shown has really been impressed.&lt;/p&gt;  &lt;h3&gt;Quick power up&lt;/h3&gt;  &lt;p&gt;This boots up very quickly, and resume from sleep is so fast (under two seconds) that it's essentially instant. This feels like a device, not a traditional laptop. I use it more because there's no wait to powering it on.&lt;/p&gt;  &lt;h3&gt;Keyboard&lt;/h3&gt;  &lt;p&gt;The keyboard seems to be a like it or hate it kind of thing. It works great for me. I've read that some people have trouble with key presses not registering, but I type pretty hard and don't have that happen at all.&lt;/p&gt;  &lt;h2&gt;Criticisms&lt;/h2&gt;  &lt;p&gt;I've only got a few minor criticisms, and all of them are pretty minor.&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;Bundleware and utilities&lt;/h3&gt;  &lt;p&gt;I mentioned this in my last review too, so I won't go into gory detail. Fresh out of the box, the Zenbook's got some simple bundleware like the Bing bar as well as a host of ASUS utilities. Some of the utilities, like the power management utilities, are worthwhile. Others like the ASUS LifeFrame application seem unlikely to be useful to most users.&lt;/p&gt;  &lt;p&gt;I don't get too upset by these for two reasons: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;They're easy to uninstall with PC Decrapifier&lt;/li&gt;    &lt;li&gt;It's a one time hit - once the laptop's set up, it's set up&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Never the less, I wish they just shipped a default Windows install and chilled out with the gadgets and utilities. I'd prefer a desktop shortcut that links to the ASUS Zenbook utility download page.&lt;/p&gt;  &lt;h3&gt;ASUS Live Update&lt;/h3&gt;  &lt;p&gt;&lt;a title="Zenbook Update" href="http://www.flickr.com/photos/36836555@N00/6793595324/"&gt;&lt;img border="0" alt="Zenbook Update" src="http://farm8.static.flickr.com/7196/6793595324_da1ee3c24e_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I don't want to deal with a separate utility for driver updates. I've already got Windows Update running, and I'd like these updates to come to me that way.&lt;/p&gt;  &lt;p&gt;What's worse, the Live Update app doesn't give feedback during some of the installs, and seemed to hang at times. I restarted it a few times because I wasn't sure if it was working.&lt;/p&gt;  &lt;p&gt;Before I installed the recommended ASUS Live Update drivers, I had two spontaneous reboots (weeks apart). After installing the drivers, I haven't seen that happen, so I'm hoping that the drivers solved things.&lt;/p&gt;  &lt;h3&gt;Power connection&lt;/h3&gt;  &lt;p&gt;I generally like the power cord. It's pretty small, and I like the light on the charging connection which makes it both easy to find the connector in the dark and to tell if it's charging or charged.&lt;/p&gt;  &lt;p&gt;The criticism is that it's a small right angle connector, and it's a little fragile. The laptop got bumped while the charger was plugged in, and it bent slightly. Everything still works, but it feels a little loose. All the other hardware is really solidly constructed, but this connection feels flimsy.&lt;/p&gt;  &lt;h3&gt;Keyboard lighting&lt;/h3&gt;  &lt;p&gt;This is more of a wish than a criticism, but I wish the keyboard were easier to use in the dark. It's pretty much the only MacBook Air feature I envy. My Lenovo has a &lt;a href="http://en.wikipedia.org/wiki/IBM_ThinkPad_ThinkLight"&gt;ThinkLight feature&lt;/a&gt;, which is just an LED light above the display that shines down on keyboard when (toggled via key combination). I'd be happy if a few of the keys had lights on them. As it is, typing in a dark room is kind of tricky.&lt;/p&gt;  &lt;h2&gt;Trackpad: works on my machine&lt;/h2&gt;  &lt;p&gt;I've heard from people who have had problems with the trackpad. Apparently there are two different trackpads that ship with this laptop, and one doesn't work as well as the other. I got the Elantech Touchpad, and it's worked great for me.&lt;/p&gt;  &lt;h2&gt;Wrap up&lt;/h2&gt;  &lt;p&gt;Overall, I'm greatly impressed with this laptop. It gives me the benefits of a device with the power of a development / work machine. If I were buying another laptop today, or recommending one to a friend, it would be this one.&lt;/p&gt;  &lt;p&gt;I'll be posting one last wrap up post in another month or two.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “&lt;/em&gt;&lt;a href="http://www.ftc.gov/os/2009/10/091005revisedendorsementguides.pdf"&gt;&lt;em&gt;Guides Concerning the Use of Endorsements and Testimonials in Advertising&lt;/em&gt;&lt;/a&gt;&lt;em&gt;”&lt;/em&gt;&lt;/p&gt;  &lt;div class="lqm_ad" lqm_publisher="lqm.jongalloway.site" lqm_zone="ron" lqm_format="1x1"&gt;&lt;/div&gt; &lt;script type="text/javascript" language="Javascript" src="http://s1.lqcdn.com/m.min.js?dt=2.3.110104.1"&gt;&lt;/script&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8318847" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=-zjDiyR1_oY:ZYNHEa5iXH0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=-zjDiyR1_oY:ZYNHEa5iXH0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=-zjDiyR1_oY:ZYNHEa5iXH0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=-zjDiyR1_oY:ZYNHEa5iXH0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=-zjDiyR1_oY:ZYNHEa5iXH0:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=-zjDiyR1_oY:ZYNHEa5iXH0:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=-zjDiyR1_oY:ZYNHEa5iXH0:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/-zjDiyR1_oY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/Review/default.aspx">Review</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/02/28/zenbook-ux31e-follow-up.aspx</feedburner:origLink></item><item><title>Juice UI: Open source ASP.NET Web Forms components for jQuery UI widgets</title><link>http://feedproxy.google.com/~r/jongalloway/~3/yuDN6Jgrcqo/juice-ui-open-source-asp-net-web-forms-components-for-jquery-ui-widgets.aspx</link><pubDate>Tue, 28 Feb 2012 19:21:20 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:8318530</guid><dc:creator>Jon Galloway</dc:creator><slash:comments>11</slash:comments><wfw:commentRss>http://weblogs.asp.net/jgalloway/rsscomments.aspx?PostID=8318530</wfw:commentRss><comments>http://weblogs.asp.net/jgalloway/archive/2012/02/28/juice-ui-open-source-asp-net-web-forms-components-for-jquery-ui-widgets.aspx#comments</comments><description>&lt;p&gt;&lt;img style="display: inline; float: right" align="right" src="http://juiceui.com/images/juice-logo.jpg" /&gt;This morning at MVP Summit, &lt;a href="http://blogs.msdn.com/b/scothu/"&gt;Scott Hunter&lt;/a&gt; just announced a new open source project from &lt;a href="http://appendto.com/"&gt;appendTo&lt;/a&gt; called &lt;a href="http://juiceui.com/"&gt;Juice UI&lt;/a&gt;. Juice UI is a collection of Web Forms components which make it incredibly easy to leverage jQuery UI widgets in ASP.NET Web Forms applications. You can start using it right away by adding the &lt;a href="http://nuget.org/packages/JuiceUI"&gt;JuiceUI NuGet package&lt;/a&gt; to your app, and you're welcome to &lt;a href="https://github.com/appendto/juiceui"&gt;go nuts with the source&lt;/a&gt;, which is dual licensed under MIT and GPL.&lt;/p&gt;  &lt;h2&gt;What Juice UI does&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt; is a library that's built on top of jQuery. It's got a lot of great widgets for common scenarios - things like date pickers, dialogs, and tabs - and they're all built on a really solid widget platform from &lt;a href="http://jqueryui.com/about"&gt;some of the sharpest Javascript developers in the field&lt;/a&gt;. You've always been able to make use of these libraries using jQuery and jQuery UI, but the new Juice UI controls make it that much easier.&lt;/p&gt;  &lt;p&gt;Example:&lt;/p&gt;  &lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;asp:TextBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;_Restrict&amp;quot; /&amp;gt;
&amp;lt;Juice:Datepicker 
    runat=&amp;quot;server&amp;quot; 
    TargetControlID=&amp;quot;_Restrict&amp;quot; 
    MinDate=&amp;quot;-20&amp;quot; 
    MaxDate=&amp;quot;+1M +10D&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;Gives you this:&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-02-28 09h16_03" href="http://www.flickr.com/photos/36836555@N00/6938942653/"&gt;&lt;img border="0" alt="2012-02-28 09h16_03" src="http://farm8.static.flickr.com/7195/6938942653_d824e09ef6_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Included controls and behaviors&lt;/h2&gt;

&lt;p&gt;Juice UI is launching with 14 widgets and behaviors. You can see the whole list of controls at &lt;a href="http://juiceui.com/controls"&gt;http://juiceui.com/controls&lt;/a&gt;, and they've all got interactive examples.&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-02-28 09h17_29" href="http://www.flickr.com/photos/36836555@N00/6938942675/"&gt;&lt;img border="0" alt="2012-02-28 09h17_29" src="http://farm8.static.flickr.com/7067/6938942675_a0cfa73dc1_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the full list, linked to the documentation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://juiceui.com/controls/accordion"&gt;Accordion&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/autocomplete"&gt;Autocomplete&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/button"&gt;Button&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/datepicker"&gt;Datepicker&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/dialog"&gt;Dialog&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/draggable"&gt;Draggable&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/droppable"&gt;Droppable&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/position"&gt;Position&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/progressbar"&gt;Progress Bar&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/resizable"&gt;Resizable&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/selectable"&gt;Selectable&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/slider"&gt;Slider&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/sortable"&gt;Sortable&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://juiceui.com/controls/tabs"&gt;Tabs&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Walkthrough&lt;/h2&gt;

&lt;h3&gt;Add the JuiceUI NuGet package&lt;/h3&gt;

&lt;p&gt;I'm going to start with a new ASP.NET 4 Web Forms project. I'll right click on the References folder, select Manage NuGet Packages..., and search for &amp;quot;juiceui&amp;quot;&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-02-28 08h10_11" href="http://www.flickr.com/photos/36836555@N00/6938942645/"&gt;&lt;img border="0" alt="2012-02-28 08h10_11" src="http://farm8.static.flickr.com/7041/6938942645_a8062f65bf_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;The JuiceUI namespace &lt;/h3&gt;

&lt;p&gt;The NuGet package adds the JuiceUI namespace to my web.config, like this:&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;compilation debug=&amp;quot;true&amp;quot; targetFramework=&amp;quot;4.0&amp;quot; /&amp;gt;
    &amp;lt;pages&amp;gt;
      &amp;lt;controls&amp;gt;
        &amp;lt;add assembly=&amp;quot;JuiceUI&amp;quot; namespace=&amp;quot;Juice&amp;quot; tagPrefix=&amp;quot;juice&amp;quot; /&amp;gt;
      &amp;lt;/controls&amp;gt;
    &amp;lt;/pages&amp;gt;
  &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;If needed, I remove that and use the &lt;a href="http://msdn.microsoft.com/en-us/library/eb44kack.aspx"&gt;&amp;lt;@Import Namespace=&amp;quot;JuiceUI&amp;quot; /&amp;gt;&lt;/a&gt; directive to bring that namespace at the page level.&lt;/p&gt;

&lt;h2&gt;Using the Juice UI controls&lt;/h2&gt;

&lt;p&gt;You'll first need an &amp;lt;asp:ScriptManager&amp;gt; - you can add one to a page, or you can add one to your site's Master page.&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;asp:ScriptManager id=&amp;quot;_Script&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now I can just start using the controls. These are extender controls, so you use the TargetControlID property to point the Juice UI behavior at an Web Forms server control. Here's a stripped down example that hooks up a DatePicker behavior to a TextBox:&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;asp:TextBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;DateSample&amp;quot; /&amp;gt;
&amp;lt;Juice:Datepicker runat=&amp;quot;server&amp;quot; TargetControlID=&amp;quot;DateSample&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;And just because it's fun, I'll add a Draggable behavior that's pointed at a Panel:&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;asp:Panel runat=&amp;quot;server&amp;quot; ID=&amp;quot;DragBox&amp;quot; Style=&amp;quot;border:1px solid; width:100px;&amp;quot;&amp;gt;
        Hi. You can drag me around.
&amp;lt;/asp:Panel&amp;gt;
&amp;lt;Juice:Draggable runat=&amp;quot;server&amp;quot; TargetControlID=&amp;quot;DragBox&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Note: I'm keeping this really simple for illustration here - of course the style would go in CSS, etc. There are more sophisticated examples in the Juice UI samples included with the source code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Running this page shows I've got just what you'd expect - a date picker on the textbox, and a draggable panel.&lt;/p&gt;

&lt;p&gt;&lt;a title="2012-02-28 10h34_32" href="http://www.flickr.com/photos/36836555@N00/6938942687/"&gt;&lt;img border="0" alt="2012-02-28 10h34_32" src="http://farm8.static.flickr.com/7180/6938942687_822f45650b_b.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the complete markup for that page:&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;%@ Page Title=&amp;quot;Home Page&amp;quot; Language=&amp;quot;C#&amp;quot; MasterPageFile=&amp;quot;~/Site.master&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot;
    CodeBehind=&amp;quot;Default.aspx.cs&amp;quot; Inherits=&amp;quot;Juice_Sample._Default&amp;quot; %&amp;gt;

&amp;lt;asp:Content ID=&amp;quot;HeaderContent&amp;quot; runat=&amp;quot;server&amp;quot; ContentPlaceHolderID=&amp;quot;HeadContent&amp;quot;&amp;gt;
&amp;lt;/asp:Content&amp;gt;
&amp;lt;asp:Content ID=&amp;quot;BodyContent&amp;quot; runat=&amp;quot;server&amp;quot; ContentPlaceHolderID=&amp;quot;MainContent&amp;quot;&amp;gt;

    &amp;lt;asp:ScriptManager id=&amp;quot;_Script&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;

    &amp;lt;asp:TextBox runat=&amp;quot;server&amp;quot; ID=&amp;quot;DateSample&amp;quot; /&amp;gt;
    &amp;lt;Juice:Datepicker runat=&amp;quot;server&amp;quot; TargetControlID=&amp;quot;DateSample&amp;quot; /&amp;gt;

    &amp;lt;asp:Panel runat=&amp;quot;server&amp;quot; ID=&amp;quot;DragBox&amp;quot; Style=&amp;quot;border:1px solid; width:100px;&amp;quot;&amp;gt;
        Hi. You can drag me around.
    &amp;lt;/asp:Panel&amp;gt;
    &amp;lt;Juice:Draggable runat=&amp;quot;server&amp;quot; TargetControlID=&amp;quot;DragBox&amp;quot; /&amp;gt;

&amp;lt;/asp:Content&amp;gt;&lt;/pre&gt;

&lt;p&gt;And, in case you're interested, the widgets are hooked up using HTML5 data- attributes:&lt;/p&gt;

&lt;pre class="brush: xml; auto-links: false;"&gt;&amp;lt;input name=&amp;quot;ctl00$MainContent$DateSample&amp;quot; type=&amp;quot;text&amp;quot; 
        id=&amp;quot;MainContent_DateSample&amp;quot; 
        data-ui-widget=&amp;quot;datepicker&amp;quot; /&amp;gt;

&amp;lt;div id=&amp;quot;MainContent_DragBox&amp;quot; 
        data-ui-widget=&amp;quot;draggable&amp;quot; 
        style=&amp;quot;border:1px solid; width:100px;&amp;quot;&amp;gt;
    Hi. You can drag me around.
&amp;lt;/div&amp;gt;&lt;/pre&gt;

&lt;h2&gt;This seems familiar...&lt;/h2&gt;

&lt;p&gt;It's a very similar experience to the Ajax Control Toolkit, but using jQuery UI as an underpinning. That is, create Web Forms extender and script controls for all the widgets and effects in jQuery UI. Don't read anything into this - work is still continuing on &lt;a href="http://ajaxcontroltoolkit.codeplex.com/"&gt;Ajax Control Toolkit&lt;/a&gt; (in fact, there have been &lt;a href="http://stephenwalther.com/blog/archive/2011/11/16/ajax-control-toolkit-november-2011-release.aspx"&gt;quite a few updates lately&lt;/a&gt;). The ASP.NET team's long term direction for client side scripting is jQuery, though, and Juice UI helps you to integrate with that really easily.&lt;/p&gt;



&lt;h2&gt;Finding out more&lt;/h2&gt;

&lt;p&gt;The best place to find out more about Juice UI is on the &lt;a href="http://juiceui.com/"&gt;Juice UI site&lt;/a&gt;, which has interactive examples and documentation.&lt;/p&gt;

&lt;p&gt;The source (including a sample project) is in the &lt;a href="https://github.com/appendto/juiceui"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd recommend getting help either on &lt;a href="http://stackoverflow.com/search?q=juiceui"&gt;StackOverflow (using the juiceui tag)&lt;/a&gt; or in the &lt;a href="http://forums.asp.net/1223.aspx/1?jQuery+for+the+ASP+NET+Developer"&gt;ASP.NET jQuery forum&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=8318530" width="1" height="1"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=yuDN6Jgrcqo:6xCfVGXGUgk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=yuDN6Jgrcqo:6xCfVGXGUgk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=yuDN6Jgrcqo:6xCfVGXGUgk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=yuDN6Jgrcqo:6xCfVGXGUgk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=yuDN6Jgrcqo:6xCfVGXGUgk:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?i=yuDN6Jgrcqo:6xCfVGXGUgk:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jongalloway?a=yuDN6Jgrcqo:6xCfVGXGUgk:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jongalloway?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jongalloway/~4/yuDN6Jgrcqo" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jgalloway/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/NuGet/default.aspx">NuGet</category><category domain="http://weblogs.asp.net/jgalloway/archive/tags/jQuery/default.aspx">jQuery</category><feedburner:origLink>http://weblogs.asp.net/jgalloway/archive/2012/02/28/juice-ui-open-source-asp-net-web-forms-components-for-jquery-ui-widgets.aspx</feedburner:origLink></item><media:rating>nonadult</media:rating></channel></rss>

