Top 10 Microsoft Developer Links for Monday, July 28, 2014

Erez Benari: MSDN magazine brings you a wealth of practical info about Azure Websites Dave Clemmer: Augmenting Test Driven Development with a Model Oriented Approach Jovan Popovic: Implement secure ASP.NET MVC applications Roland Kuhn: Go Reactive: Blueprint for Future Applications Manuel Pais: The Birth of Continuous Delivery and DevOps Alkampfer's Place: Your TFS keeps asking you for credentials even with Active Directory Visual Studio Toolbox: Load Testing Programming Kinect for Windows: Introducing Kinect Development Devon Musgrave: Free ebook: Building Cloud Apps with Microsoft Azure The Register: NO MORE ALL CAPS and other pleasures of Visual Studio 14 2095

Posted by on 28 July 2014 | 1:14 pm

Top 10 Microsoft Developer Links for the Week of July 21, 2014

Jonathan Turner: New Compiler and Moving to GitHub Jeff Bramwell: Visual Studio/TFS 2013 Update 3–Release Candidate Developer.com: Writing Code that Writes Code Brian Harry: Visual Studio Online Update – July 21 Visual Studio Blog: Node.js Tools for Visual Studio 1.0 Beta 2 Available John Musser: 10 Reasons Why Developers Hate Your API Bodil Stokke: What Every Hipster Should Know About Functional Reactive Programming David Rousset: How to remotely debug and profile the performance of your HTML5 websites & apps on Windows Phone Grant Shipley: Presentation: Full Stack JavaScript Rahul Rajat Singh: Understanding, Using and Customizing ASP.NET Identity System for Authentication and Authorization 2094

Posted by on 28 July 2014 | 1:13 pm

Developing with Kinect for Windows v2 on a Mac

With the launch of the Kinect for Windows v2 public preview, we want to ensure that developers have access to the SDK so that you can start writing Kinect-based applications. As you may be aware, the Kinect for Windows SDK 2.0 public preview will run only on Windows 8 and Windows 8.1 64-bit systems. If you have a Windows 8 PC that meets the minimum requirements, you’re ready to go. For our Macintosh developers, this may be bittersweet news, but we’re here to help. There are two options available for developers who have an Intel-based Mac: (1) install Windows to the Mac’s hard drive, or (2) install Windows to an external USB 3.0 drive. Many Mac users are aware of the first option, but the second is less well known. First, you need to ensure that your hardware meets the minimum requirements for Kinect for Windows v2. Due to the requirements for full USB 3.0 bandwidth and GPU Shader Model 5 (DirectX 11), virtualization products such as VMWare Fusion, Parallels Desktop, or Oracle VirtualBox are not supported. If you’re not sure what hardware you have, you can find out on these Apple websites: Mac notebooks (MacBook Air or Pro) Mac desktops (iMac or MacPro)  Installing Windows on the internal hard drive of your Intel-based Macintosh We’re going to focus on getting Windows 8.1 installed, since this is typically the stumbling block. (If you need help installing Visual Studio or other applications on Windows, you can find resources online.) Apple has provided a great option called Boot Camp. This tool will download the drivers for Windows, set up bootable media for installation, and guide you through the partitioning process. Please refer to Apple’s website on using this option: Boot Camp Support Boot Camp: System requirements for Microsoft Windows operating systems Boot Camp: Frequently asked questions about installing Windows 8 Alternative to installing Windows on your primary drive Boot Camp requires Windows to be installed on your internal hard drive. This might be impractical or impossible for a variety of reasons, including lack of available free space, technical failures during setup, or personal preferences. An alternative is to install Windows to an external drive using Windows To Go, a feature of Windows 8 and 8.1 Enterprise. (Learn more about this feature in Windows 8.1 Enterprise.) In the section, Hardware considerations for Windows To Go, on Windows To Go: Feature Overview, you can find a list of recommended USB 3.0 drives. These drives have additional security features that you may want to review with your systems administrators, to ensure you are in compliance with your company’s security policies. Getting started with Windows To Go You will need the following to proceed: Existing PC with USB 3.0 that has Windows 8/8.1 Enterprise installed (the “technician computer”) USB 3.0 flash or external hard drive Windows 8/8.1 Enterprise installation media (CD or ISO) Windows 8/8.1 product key You will need to log in as the administrator. Start the Windows to Go tool, press Win-Q to start the search, and enter Windows To Go: Launch the Windows To Go application from the list. From the main application window, you will see a list of the attached drives that you can use with the tool. As shown below, you may be alerted of USB 3.0 drives that are not Windows To Go certified. You can still use the drive but understand that it might not work or could have an impact on performance. If you are using a non-certified USB 3.0 drive, you will have do your own testing to ensure it meets your needs. (Note: while not officially supported by Microsoft, we have used the Western Digital My Passport Ultra 500 GB and 1 TB drives at some of our developer hackathons to get people using Macs up and running with our dev tools on Windows.) Select the drive you wish to use and click Next. If you have not already done so, insert the Windows 8.1 Enterprise CD at this time. If you have the .ISO, you can double-click the icon or right-click and select Mount to use it as a virtual drive. If you do not see an image in the list, click the Add search location button and browse your system to find the DVD drive or mounted CD partition: It should now appear in the list, and you can select it and click Next. If you need or wish to use BitLocker, you can enable that now. We will Skip this.   The confirmation screen will summarize the selections you have made. This is your last chance to ensure that you are using the correct drive. Please avail yourself of this opportunity, as the Windows To Go installation process will reformat the drive and you will not be able to recover any data that is currently on the drive. Once you have confirmed that you are using the correct drive, click Create to continue. Once the creation step is complete, you are ready to reboot the system. But first, you’ll need to download the drivers necessary for running Windows on Macintosh hardware from the Apple support page, as, by default, Windows setup does not include these drivers. I recommend that you create an Extras folder on your drive and copy the files you’ll need. As shown below, I downloaded and extracted the Boot Camp drivers in this folder, since this will be the first thing I’ll need after logging in for the first time. Disconnect the hard drive from the Windows computer and connect it to your Mac. Be sure that you are using the USB 3.0 connection if you have both USB 2 and USB 3.0 hardware ports. Once the drive is connected, boot or restart your system while holding down the option key. (Learn more about these startup key shortcuts for Intel-based Macs.) During the initial setup, you will be asked to enter your product key, enter some default settings, and create an account. If your system has to reboot at any time, repeat the previous step to ensure that you return to the USB 3.0 workspace. Once you have successfully logged in for the first time, install the Boot Camp driver and any other applications you wish to use. Then you’ll have a fully operational Windows environment you can use for your Kinect for Windows development. Carmine Sirignano Developer Support Escalation Engineer Kinect for Windows Key links Learn more about Kinect for Windows Download the SDK 2.0 public preview Purchase the v2 sensor Visit our technical forums See Kinect for Windows applications in action Follow us on Facebook and Twitter  

Posted by on 28 July 2014 | 12:59 pm

3 Challenges to Help You Set New Benchmarks in Innovation

If you want to change your game, you need to know what the key challenges are. Innovation is a game that you can play much better, if you know where and how to debottleneck it. In the book The Future of Management, Gary Hamel shares 3 challenges that he believes can help you unleash your organization’s capacity for innovation. How can you enroll every individual within your company in the work of innovation, and equip each one with creativity-boosting tools? How can you ensure that top management's hallowed beliefs don't straightjacket innovation, and that heretical ideas are given the chance to prove their worth? How can you create the time and space for grassroots innovation in an organization that is running flat to deliver today's results? According to Hamel, "Make progress on these challenges and your company will set new benchmarks in innovation." If I think back through the various teams I’ve been on at Microsoft, one team that I was on was especially good at helping innovation flourish, and we were constantly pushing the envelope to “be what’s next.”   Our innovation flourished the most when we directly addressed the challenges above.  People were challenged to share and test their ideas more freely and innovation was baked into how we planned our portfolio, programs, and projects. Innovation was a first-class citizen – by design. You Might Also Like High-Leverage Strategies for Innovation Innovation Life Cycle Lessons Learned from the Most Successful Innovators The Drag of Old Mental Models on Innovation and Change The New Realities that Call for New Organizational and Management Capabilities

Posted by on 28 July 2014 | 12:39 pm

OneNote tip - controlling the footer when printing

A OneNote user was printing from OneNote last week and when she printed, she kept seeing a little date marker at the bottom of the printed page. She did not want this little footer and sent me a mail to ask if that could be turned off. To turn off the footer, click File | Print and then select Print Preview. You will get a dialog that looks like this: Near the bottom right is the Footer control - you can set the Footer to print the name of the section + the page number, or just the number, or just the section name or turn it off by setting to (none). I let her know and followed up later. This worked for her and now she can print OneNote pages without that little extra bit of text she did not want at the bottom. Questions, comments, concerns and criticisms always welcome, John

Posted by on 28 July 2014 | 11:25 am

Pôsters para download

Para quem estava procurando para baixar algum pôster da Microsoft então vai gostar desta dica. A área de Cidadania da Microsoft disponibilizou alguns para download e são focados para estudantes e empresas. Link para download: http://www.microsoft.com ...read more...(read more)

Posted by on 28 July 2014 | 11:02 am

Include Office content in your web pages

As some of you know, one of my team’s core focus is to enable developers to build amazing solutions on top of Office 365. And over the last few months, we’ve released a lot of new extensibility features, documentation, samples and open source projects to support the ecosystem. In this blog post, I wanted to share an extensibility tip which is super easy that any user can do without writing code – embed Office files in any web page, including blog posts, using the power of Office Online. This is a very simple, yet powerful way, of displaying dynamic spreadsheets, presentations and word documents. You can do this for documents stored in OneDrive and OneDrive for Business. So how do you do it? In OneDrive, it’s very straightforward and visible in the standard navigation. You just go to http://www.onedrive.com, sign-in, select the file you want to embed and then click on “Embed” at the top to copy the HTML code. You also have the option to embed a folder under Folder Actions –> Embed Folder. So if you have a public folder, you can share it easily with everyone. If you want to embed a file, the key is to select the file so you get the Embed option in the top nav. This, as you would expect, respects the OneDrive security permissions that have been configured.   The actual code is below. The parameters are straightforward and you can easily change them. <iframe src="https://onedrive.live.com/embed?cid=CA582F2BC3AD1590&resid=CA582F2BC3AD1590%2133463&authkey=AFh1O3tkDLAQzzw&em=2" width="402" height="327" frameborder="0" scrolling="no"></iframe>   So in this example, here’s my Copenhagen Ignite keynote presentation embedded in this blog post that I’ve shared with everyone:   You can do this for other Office file types as well. Here’s a demo Excel file hosted on my personal OneDrive in the same folder:   The TechNet team took advantage of the power of embedding Office files in web pages in their Office 365 service comparison page @ http://technet.microsoft.com/en-us/office/dn788955. So what about embedding documents stored in OneDrive for Business? You can do the same thing – you just have to do a little more work to find the HTML code to embed the doc. Like before, security permissions are respected. For PowerPoint and Word files, you can find the HTML code in the document preview under the “Embed Information” option in the document library (see below).     Below is the code. This has more extraneous HTML code, but is similarly constructed with parameters for a document id, width and height. One thing that’s missing is an authkey. This code requires someone to be authenticated. <iframe src='https://retreat-my.sharepoint.com/personal/katiej_retreat_onmicrosoft_com/_layouts/15/WopiFrame.aspx?sourcedoc={f19600ba-968f-4922-95e2-15c38051641f}&action=embedview&wdAr=1.7755102040816326&Embed=1' width='350px' height='221px' frameborder='0'>This is an embedded <a target='_blank' href='http://office.com'>Microsoft Office</a> presentation, powered by <a target='_blank' href='http://office.com/webapps'>Office Online</a>.</iframe> For Excel files, there’s no UX to grab the HTML code. You need to take the HTML code from any PowerPoint/Word file and replace the sourcedoc GUID with the Excel file GUID. You can easily get the Excel GUID by viewing the Excel file with Excel Online – it will be in the URL string.   Here’s a screenshot of how I embedded a PowerPoint and Excel file hosted in my OneDrive for Business on a SharePoint page using Page Viewer web parts. As you would expect, when I embed the Excel file, I also get the App for Excel that was inserted into the file – very cool.   This is pretty straightforward when you’re looking to embed files in an authenticated intranet/extranet scenario, but how do you embed Office files hosted in OneDrive for Business in anonymous scenarios? Assuming your IT admin has allowed for external anonymous sharing (more info on that here), you need to select the file you want to share, choose share, choose “get a link” and then create a link.      Here’s the guest link: https://retreat-my.sharepoint.com/personal/katiej_retreat_onmicrosoft_com/_layouts/15/guestaccess.aspx?guestaccesstoken=PGwTbjYxjgofpMWZGdILVEp7dYFkiW%2fK35sQZqNI3z4%3d&docid=0fb3ee47f64fa49e0828e732992c8fb51 You’ll notice that the guest access token and docid are parameters. You can use this to construct the embed HTML URL as follows: <iframe height="221" src="https://retreat-my.sharepoint.com/personal/katiej_retreat_onmicrosoft_com/_layouts/15/WopiFrame.aspx?guestaccesstoken=PGwTbjYxjgofpMWZGdILVEp7dYFkiW%2fK35sQZqNI3z4%3d&docid=0fb3ee47f64fa49e0828e732992c8fb51&action=embedview" frameborder="0" width="350"></iframe> For example, here’s the PowerPoint session hosted on my Office 365 demo tenant’s that I presented at WPC with my colleague Tanuj Bansal: So have fun trying some of these tips out! It's clearly not for every scenario, but can be powerful to help tell your story, share content and let your customers analyze data on your web pages.

Posted by on 28 July 2014 | 11:00 am

Org Navigator: a Mobile App leveraging Azure AD Graph

new post! http://www.cloudidentity.com/blog/2014/07/28/org-navigator-a-mobile-app-leveraging-azure-ad-graph/...(read more)

Posted by on 28 July 2014 | 10:39 am

Why SharePoint on Azure?

Editor’s note: In partnership with Microsoft Press, now celebrating their 30th year, MVPs have been contributing to an ongoing guest series on their official team blog. Today’s article is from SharePoint MVP Tom Resing which is the43rd in the series.  Why SharePoint on Azure? Last week, at the Worldwide Partner Conference, a new SharePoint Farm option for Azure was announced. The new SharePoint Farm Gallery option from the Azure Portal is now, by far, the easiest way to get started with SharePoint on Azure. Type in a name for the Farm’s Azure Resource Group and credentials for the Administrator account, and the rest of the farm creation is automated.     SharePoint in the Cloud As you may know, Office 365 includes SharePoint Online as a component. If you want to do SharePoint in the Cloud, it doesn’t get any easier to set up or less expensive than Office 365. If it’s not easier or less expensive, why chose Azure over Office 365? The TechNet article Microsoft Azure Architectures for SharePoint 2013, gives 4 reasons: 1)      Development and Test 2)      Disaster Recovery 3)      Internet Sites 4)      App Farms Development and Test From the beginning of my time working with SharePoint, creating and maintaining development and test environments has consumed a very large amount of my time. I started in the early days in 2006 when VMWare was my only option. Then my Microsoft Certified Master training and tests 4 years later required me to learn Hyper-V. Along the way, I made good use of the excellent online environments at Cloudshare.com. I’ve tried it all. To this day, I still maintain a SharePoint 2013 environment locally on my laptop for demonstrations. When I trust I can get reliable internet connections presenting at all conferences, I’ll be ready to trade that heavy laptop in for a more nimble machine and an Azure Farm. Today, development environments in Azure are easy and can be done pretty much for free, with an MSDN license. Here’s a great chart authored by Simon J.K. Pedersen on the cost: Machine Pricing Tier RAM Cores Price/Hour (Pay-As-You-Go) Price/Hour (MSDN) Domain Controller Basic A1 1.75 1 $0.075 $0.047 SQL Server Standard A5 14 2 $2.10 $0.248 SharePoint Server Standard A5 14 2 $0.30 $0.248 With these prices you will be able to run your environment for around 276 hours, or more than 30 days if it is only online 8 hours a day, on a Visual Studio Ultimate MSDN subscription with $150 Azure Credit (MSDN subscribers don’t pay extra SQL servers and only pay linux prices for the VMs). If you are not using an MSDN subscription, your price will obviously be a lot higher. Disaster Recovery Azure offers a great option for a secondary location for your on-premises SharePoint farm. You can really take advantage of the on-demand nature of cloud infrastructure as a service in many disaster recovery scenarios. Continue reading full article here About the author Tom is an advocate for, architect of and developer of web sites and has been for almost 20 years. He's been very lucky to work with some of the best tools available in the web development world like Visual Studio, IIS, SharePoint and Azure. Tom has received 2 MVP Awards in SharePoint for his community contributions including writing, speaking at and organizing technical events.  Follow him on Twitter. About MVP Mondays The MVP Monday Series is created by Melissa Travers. In this series we work to provide readers with a guest post from an MVP every Monday. Melissa is a Community Program Manager, formerly known as MVP Lead, for Messaging and Collaboration (Exchange, Lync, Office 365 and SharePoint) and Microsoft Dynamics in the US. She began her career at Microsoft as an Exchange Support Engineer and has been working with the technical community in some capacity for almost a decade. In her spare time she enjoys going to the gym, shopping for handbags, watching period and fantasy dramas, and spending time with her children and miniature Dachshund. Melissa lives in North Carolina and works out of the Microsoft Charlotte office.      

Posted by on 28 July 2014 | 10:32 am

eBook deal of the week: Exam Ref 70-410: Installing and Configuring Windows Server 2012 R2

List price: $31.99   Sale price: $16.00 You save 50% Buy Fully updated for Windows Server 2012 R2! Prepare for Microsoft Exam 70-410 - and help demonstrate your real-world mastery of implementing and configuring core services in Windows Server 2012 R2. Designed for experienced IT professionals ready to advance their status, Exam Ref focuses on the critical thinking and decision making acumen needed for success at the MCSA level. Learn more Terms & conditions Each week, on Sunday at 12:01 AM PST / 7:01 AM GMT, a new eBook is offered for a one-week period. Check back each week for a new deal. The products offered as our eBook Deal of the Week are not eligible for any other discounts. The Deal of the Week promotional price cannot be combined with other offers.

Posted by on 28 July 2014 | 10:25 am

Accessibility Captures the Imagination of Finalists at the 2014 Microsoft Imagine Cup

The following blog post was written by Paul Nyhan, a staff writer with the Microsoft Accessibility Blog. Paul is a 20-year journalism veteran who has written extensively about disability issues. ----- When the Microsoft Imagine Cup finals open this week accessibility will be in the middle of the competition, with apps that help people with vision, mobility, and hearing impairments vying to win. This year accessibility is a growing force in the Imagine Cup - the world’s leading technology...(read more)

Posted by on 28 July 2014 | 9:46 am

Hotfix1 til Microsoft Dynamics C5 2010 SP2

I forbindelse med yderligere test af Microsoft Dynamics C5 2012 Service Pack 2 (4.4.02.000) er der blevet konstateret enkelte tilfælde hvor driftsføring af kostpris reguleringer i projektmodulet ikke fungerer korrekt hvis reguleringerne er foretaget efter installation af Service Pack: driftsførte beløb og/eller drifts- og statuskonti i driftsføringshistorik kan afvige fra de faktiske mens beløb som burde være bogført på en statuskonto (igangværende arbejder) kan være bogført på fejlkontoen. Dette gælder især omkostningsposteringer som stammer fra projektlinjer i modsætning til dem som stammer fra projektkladde. Derfor frigiver vi HotFix1 til Microsoft Dynamics C5 2012 Service Pack 2. I samme forbindelse frigiver vi en kerneopdatering med et par mindre rettelser. Som altid - læs mere i den medfølgende dokumentation. Direkte links: Hotfix 1 for Microsoft Dynamics C5 2012 SP2 Native Hotfix 1 for Microsoft Dynamics C5 2012 SP2 SQL   Link til PartnerSource her(Er dog først aktive tidligst tirsdag den 29. juli om eftermiddagen)  

Posted by on 28 July 2014 | 9:15 am

Starting Elevated PowerShell Windows

There are a few commands I have to run from Elevated PowerShell windows (such as suspending Bitlocker prior to patching).  It’s not that hard to right-click on my pinned-to-taskbar PowerShell icon and select “Run as Administrator”, but I wanted to see if I could avoid that.  I can, somewhat.  This throws up the UAC prompt once to create the scheduled task. It creates an icon on your desktop with the name “PSH (Admin)”. Double-click on this, and you’re in an elevated window. $taskName...(read more)

Posted by on 28 July 2014 | 9:00 am

Finding the shortest path to the ground while avoiding obstacles

Today's Little Program solves the following problem: Consider a two-dimensional board, tall and narrow. Into the board are nailed a number of horizontal obstacles. Place a water faucet at the top of the board and turn it on. The water will dribble down, and when it hits an obstacle, some of the water will go left and some will go right. The goal is to find the shortest path to the ground from a given starting position, counting both horizontal and vertical distance traveled. ⬤ • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • In the above diagram, the water falls three units of distance until it encounters Obstacle 1, at which some goes to the left and some goes to the right. The water that goes to the left travels three units of distance before it reaches the end of the obstacle, then falls three units and encounters Obstacle 2. Upon reaching Obstable 2, the water can again choose to flow either left or right. The water that flows to the left falls to the ground; the water that flows to the right falls and encounters a third obstacle. From the third obstacle, the water can flow left or right, and either way it goes, it falls to the ground. On the other hand, the water that chose to flow to the right when it encountered Obstable 1 iwould fall past Obstacle 2 (which is not in a position to intercept the water) and land directly on Obstacle 3. In the above scenario, there are five paths to the ground. From Obstacle 1, flow left, then from Obstacle 2, flow left again. Total distance traveled: 17 units. From Obstacle 1, flow left, then from Obstacle 2, flow right, then from Obstacle 3, flow left. Total distance traveled: 18 units. From Obstacle 1, flow left, then from Obstacle 2, flow right, then from Obstacle 3, flow right. Total distance traveled: 20 units. From Obstacle 1, flow right, then from Obstacle 3, flow left. Total distance traveled: 16 units. From Obstacle 1, flow right, then from Obstacle 3, flow right. Total distance traveled: 14 units. In this case, the shortest path to the ground is the last path. There are many ways to attack this problem. The brute force solution would be to enumerate all the possible paths to the ground, then pick the shortest one. A more clever solution would use a path-finding algorithm like A*, where the altitude above the ground is the heuristic. In both cases, you can add an optimization where once you discover two paths to the same point, you throw out the longer one. This may short-circuit future computations. But I'm going to use an incremental solution, since it has the advantage of incorporating the optimization as a convenient side-effect. Instead of studying individual drops of water, I'm going to study all of them at once. At each step in the algorithm, the data structures represent a horizontal cross-section of the above diagram, representing all possible droplet positions at a fixed altitude. In addition to collapsing redundant paths automatically, this algorithm has the nice property that it can be done as an on-line algorithm: You don't need to provide all the obstacles in advance, as long as the obstacles are provided in order of decreasing altitude. Instead of presenting the raw code and discussing it later (as is my wont), I'll explain the code as we go via code comments. We'll see how well that works. I originally wrote the program in C# because I thought I would need one of the fancy collection classes provided by the BCL, but it turns out that I didn't need anything fancier than a hash table. After I wrote the original C# version, I translated it to JavaScript, which is what I present here. The inputs which correspond to the diagram above are Initial X position = 6, Initial Y position = 12 Obstacle: Left = 3, Right = 7, height = 9 Obstacle: Left = 1, Right = 5, height = 6 Obstacle: Left = 4, Right = 8, height = 3 And here's the program. function Obstacle(left, right, y) { this.left = left; this.right = right; this.y = y; } // A single step in a path, representing the cost to reach that point. function Step(x, y, cost) { this.x = x; this.y = y; this.cost = cost; } // Add a step to an existing step Step.prototype.to = function to(x, y) { var dx = Math.abs(this.x - x); var dy = Math.abs(this.y - y); return new Step(x, y, this.cost + dx + dy); } // Record a droplet position function addDroplet(l, step) { // If no previous droplet at this position or the new droplet // has a cheaper path, then remember this droplet. var existingStep = l[step.x]; if (!existingStep || step.cost < existingStep.cost) { l[step.x] = step; } } // Take an existing collection of locations and updates them to account // for a new obstacle. Obstacles must be added in decreasing altitude. // (Consecutive duplicate altitudes allowed.) function fallTo(oldLocations, obstacle) { var newLocations = {}; for (var x in oldLocations) { var step = oldLocations[x]; // fall to the obstacle's altitude step = step.to(step.x, obstacle.y); // If the falling object does not hit the obstacle, // then there is no horizontal displacement. if (step.x <= obstacle.left || step.x >= obstacle.right) { addDroplet(newLocations, step); } else { // The falling object hit the obstacle. // Split into two droplets, one that goes left // and one that goes right. addDroplet(newLocations, step.to(obstacle.left, obstacle.y)); addDroplet(newLocations, step.to(obstacle.right, obstacle.y)); } } return newLocations; } function printStep(step) { console.log("Cost = " + step.cost + ": " + step.x + "," + step.y); } // Debugging function function printLocations(l) { for (var x in l) printStep(l[x]); } function shortestPath(x, y, obstacles) { var l = {}; l[x] = new Step(x, y, 0); printLocations(l); obstacles.forEach(function (obstacle) { l = fallTo(l, obstacle); console.log(["after", obstacle.left, obstacle.right, obstacle.y].join(" ")); printLocations(l); console.log("==="); }); // Find the cheapest step. var best; for (x in l) { if (!best || l[x].cost < best.cost) best = l[x]; } // Fall to the floor and print the result. printStep(best.to(best.x, 0)); } shortestPath(6,12,[new Obstacle(3,7,9), new Obstacle(1,5,6), new Obstacle(4,8,3)]); This program finds the cost of the cheapest path to the floor, but it merely tells you the cost and not how the cost was determined. To include the winning path, we need to record the history of how the cost was determined. This is a standard technique in dynamic programming: In addition to remembering the best solution so far, you also remember how that solution was arrived at by remembering the previous step in the solution. You can then walk backward through all the previous steps to recover the full path. // A single step in a path, representing the cost to reach that point // and the previous step in the path. function Step(x, y, cost, previous) { this.x = x; this.y = y; this.cost = cost; this.previous = previous; } // Add a step to an existing step Step.prototype.to = function to(x, y) { var dx = Math.abs(this.x - x); var dy = Math.abs(this.y - y); // These next two test are not strictly necessary. They are for style points. if (dx == 0 && dy == 0) { // no movement return this; } else if (dx == 0 && this.previous && this.previous.x == x) { // collapse consecutive vertical movements into one return new Step(x, y, this.cost + dx + dy, this.previous); } else { return new Step(x, y, this.cost + dx + dy, this); } } function printStep(firstStep) { // Walk the path backwards, then reverse it so we can print // the results forward. var path = []; for (var step = firstStep; step; step = step.previous) { path.push("(" + step.x + "," + step.y + ")"); } path.reverse(); console.log("Cost = " + firstStep.cost + ": " + path.join(" ")); } Notice that we didn't change any of the program logic. All we did was improve our record-keeping so that the final result prints the full path from the starting point to the ending point.

Posted by on 28 July 2014 | 9:00 am

Web Sites en Azure con PHP, MySQL vía FTP

En esta guía vamos a ver como con mínimo esfuerzo y sin software adicional podemos tener corriendo nuestro sitio web en Azure Web Sites. En este punto, entiendo que ya tenés creada tu cuenta de Azure. Si aún no la tenés, te dejo algunas opciones para que empieces gratis: Free trial Subscriptores MSDN Miembros de BizSpark Bien. Si tu cuenta ya está activa, entremos al portal de Azure en esta dirección: https://manage.windowsazure.com/ Una vez que cargue, vas a ver algo como esto, sólo que seguramente con menos cosas listadas (yo ya tengo muchos servicios corriendo en mi cuenta). Creemos primero el servicio de hosting para el sitio web. Click en New > Compute > Web Site > Custom Create. Vas a ver algo como esto:   Como puedes ver, el nombre de tu sitio web es el que va a definir la dirección URL, para la cual el patrón siempre es <miURL>.azurewebsites.net. Si en realidad lo que necesitas es redirigir www.midominio.com a este sitio web, más adelante explico como hacerlo. Ejemplo: yo elegí mfelman-phpsite, por lo tanto, mi dirección será mfelman-phpsite.azurewebsites.net. Además, yo tengo www.marcelofelman.com.ar y quiero poder acceder de esa forma. Esto es posible y lo vemos mas adelante. Bien, ahora que tenemos esta pantalla, elegimos Create a new MySQL database. En caso de que ya tengamos otra base existente y querramos conectarnos a ella, esa posibilidad existe también y lo vemos más adelante. NOTA: fíjate bien que la base de datos y el sitio web estén en la misma región. Esto es importante por motivos de performance. Yo elijo Sur de Brasil por motivos que explico en este post. Bien, en base al repositorio de código que uses, elegís esta opción. Para tratar de ser lo más genérico posible, yo voy a hacer un deployment con FTP (por lo tanto no requiero tildar Publish from source control). Nota: si no usas ningún repositorio de código, te sugiero que no tildes la cajita de Publish from source control y subí el sitio web mediante FTP al igual que yo. Ahora, seguimos estos pasos:   Una vez que tenemos lo anterior, copia link de FTP HOST NAME y abrilo con el Explorador de Windows (Mi PC). Nos va a aparecer una ventana como la siguiente, a la cual debemos acceder con el usuario debajo de DEPLOYMENT / FTP USER (marcado en amarillo). Ahora vayamos a site > wwwroot, ahí están los archivos de nuestro sitio web: Simplemente, pegamos los archivos ahí. Para hacer una prueba sencilla, acabo de crear un archivo . php (con bloc de notas) que imprime por pantalla “Hola nube”. Probá hacer lo mismo, y pega el archivo en la carpeta anterior. (Ya sé, ya sé, me gustan los íconos grandes, no me juzgues…) Listo. Ahora entra a <tusitioweb>.azurewebsites.net y tendrías que ver algo como esto: Listo. Ya está corriendo desde Brasil el archivo que acabas de crear. Conectarse a la base de datos MySQL Bueno, acá ya hicimos algo super fácil. Agreguemos la conexión a la base de datos que tampoco debería ser complejo. Para tomar la información de conexión, volvemos al portal y buscamos View connection strings.   Busquemos los siguientes campos: Y reemplazamos en el código de conexión, que es el siguiente: Luego escribamos algo de código como para probar que funcione: Acá está el código por si querés copiarlo. <?php // Información de conexión a la base $host = "Data source"; $user = "Usuario"; $pwd = "Password"; $db = "Base de datos"; try{     $conn = new PDO( "mysql:host=$host;dbname=$db", $user, $pwd);     $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );     $sql = "CREATE TABLE registration_tbl(                 id INT NOT NULL AUTO_INCREMENT,                 PRIMARY KEY(id),                 name VARCHAR(30),                 email VARCHAR(30),                 date DATE)";     $conn->query($sql); } catch(Exception $e){     die(print_r($e)); } echo "<h3>Table creada!</h3>"; ?> Ahora como hicimos antes, copiar y pegar en wwwroot del FTP: Dale Yes to All. Eso fue fácil. Si probamos entrar de nuevo, deberíamos recibir una excepción ya que estamos tratando de crear una tabla que ya existe, ¿no? Perfecto. Tabla creada, sitio funcionando. Estos pasos te sirven para entrar a un tablero de administración de tu sitio web: Acá tenés el dashboard de tu base de datos MySQL (online). Te recomiendo que le pegues una revisada ya que hay algunas cosas interesantes que podés ver desde ahí.   Ya podemos subir, administrar y demás. Sólo te queda armar el sitio, pero eso ya no es parte de Azure. Dominios Azure por el momento no ofrece servicios de DNS. Por lo tanto, si ya contas con tu www.misitio.com, simplemente lo que debes hacer es redirigir el CNAME a la dirección que te provee Azure, que es <Nombre de mi servicio>.azurewebsites.net.

Posted by on 28 July 2014 | 7:18 am

From the MVPs: Why SharePoint on Azure?

This is the 43rd in our series of guest posts by Microsoft Most Valued Professionals (MVPs). You can click the “MVPs” tag in the right column of our blog to see all the articles. Since the early 1990s, Microsoft has recognized technology champions around the world with the MVP Award. MVPs freely share their knowledge, real-world experience, and impartial and objective feedback to help people enhance the way they use technology. Of the millions of individuals who participate in technology communities, around 4,000 are recognized as Microsoft MVPs. You can read more original MVP-authored content on the Microsoft MVP Award Program Blog. This post is by SharePoint Server MVP Tom Resing. Thanks, Tom! Why SharePoint on Azure? Last week, at the Worldwide Partner Conference, a new SharePoint Farm option for Azure was announced. The new SharePoint Farm Gallery option from the Azure Portal is now, by far, the easiest way to get started with SharePoint on Azure. Type in a name for the Farm’s Azure Resource Group and credentials for the Administrator account, and the rest of the farm creation is automated. SharePoint in the Cloud As you may know, Office 365 includes SharePoint Online as a component. If you want to do SharePoint in the Cloud, it doesn’t get any easier to set up or less expensive than Office 365. If it’s not easier or less expensive, why chose Azure over Office 365? The TechNet article Microsoft Azure Architectures for SharePoint 2013, gives 4 reasons: 1) Development and Test 2) Disaster Recovery 3) Internet Sites 4) App Farms Development and Test From the beginning of my time working with SharePoint, creating and maintaining development and test environments has consumed a very large amount of my time. I started in the early days in 2006 when VMWare was my only option. Then my Microsoft Certified Master training and tests 4 years later required me to learn Hyper-V. Along the way, I made good use of the excellent online environments at Cloudshare.com. I’ve tried it all. To this day, I still maintain a SharePoint 2013 environment locally on my laptop for demonstrations. When I trust I can get reliable internet connections presenting at all conferences, I’ll be ready to trade that heavy laptop in for a more nimble machine and an Azure Farm. Today, development environments in Azure are easy and can be done pretty much for free, with an MSDN license. Here’s a great chart authored by Simon J.K. Pedersen on the cost: Machine Pricing Tier RAM Cores Price/Hour (Pay-As-You-Go) Price/Hour (MSDN) Domain Controller Basic A1 1.75 1 $0.075 $0.047 SQL Server Standard A5 14 2 $2.10 $0.248 SharePoint Server Standard A5 14 2 $0.30 $0.248 “With these prices you will be able to run your environment for around 276 hours, or more than 30 days if it is only online 8 hours a day, on a Visual Studio Ultimate MSDN subscription with $150 Azure Credit (MSDN subscribers don’t pay extra SQL servers and only pay linux prices for the VMs). If you are not using an MSDN subscription, your price will obviously be a lot higher.” Disaster Recovery Azure offers a great option for a secondary location for your on-premises SharePoint farm. You can really take advantage of the on-demand nature of cloud infrastructure as a service in many disaster recovery scenarios. For example, you might maintain a minimum resource farm during stand-by, allowing transactions to post from your on-premises farm. In case of recovery need, you could easily scale out the farm to provide full production-scale very quickly. Internet Sites Azure is better suited for many needs of hosting internet sites leveraging SharePoint. TechNet gives 4 reasons to use Azure for internet sites. 1) Versus an on-premises install, Azure requires much less infrastructure work. 2) You can size your farm for demand. Many internet sites vary in their demand, seasonality or special events can cause high demand, requiring more resources temporarily. 3) Azure Active Directory – while all SharePoint Farms require a true Active Directory server for backend services, the cloud based directory service can be leveraged for user logins. It’s not stated specifically, but you may not be able to leverage Azure Active Directory with Office 365. 4) Other SharePoint functionality not available in Office 365. TechNet points out reporting and web analytics as examples. This internet sites scenario may also apply to large enterprise intranets which may not be appropriate for Office 365 for the same reasons. App Farms Honestly, I’m not sure if TechNet is referring to Application Servers, as in search or content processing roles, or SharePoint Apps, the new development model for SharePoint 2013. Their reasons seem to cover both: Build, test, and host apps in Azure to support both on-premises and cloud environments. Host this role in Azure instead of buying new hardware for on-premises environments. Either way, it could make sense. Development and Test was already covered. Hosting App Model services in Azure also makes sense, though not always in a SharePoint Farm. A support farm could also make sense. The TechNet article Share service applications across farms in SharePoint 2013 lists 6 service applications that can be shared across server farms: 1) Business Data Connectivity 2) Machine Translation 3) Managed Metadata 4) User Profile 5) Search 6) Secure Store One Azure Management Tip As a final tip on using the new Azure SharePoint Farm option, I suggest using a mix of the old and the new. The new https://portal.azure.com site must be used for creating the SharePoint Farm the easy way. However, I prefer the older https://manage.windowsazure.com site for many Azure tasks. For example, during the creation of a new Highly Available farm on the new portal site, I get the following message as my total progress report: While, it says it will be ready in a moment, in my experience, it takes more than an hour for this notification to change. During the process, I prefer to monitor the progress on the old management site. On the old site, I can see the new servers in the farm appear as they are created. In addition, after the servers are created, you can find additional information on the old site you don’t see on the new site. For example, the external IP address is easily available on the old site. Conclusion Azure provides reliable, on-demand infrastructure services. SharePoint demands a lot of infrastructure resources. Marrying the two makes perfect sense to me. If you want to read more from me on the subject, visit The New Azure SharePoint Farm Option on my blog http://tomresing.com.

Posted by on 28 July 2014 | 5:00 am

Apps in Education: Discover a new generation of Microsoft tools for education (new infographic)

Educators will be familiar with Blooms Taxonomy of Educational objectives, which classifies orders of thinking. Now Microsoft has a range of tools specifically designed to support pupils through this learning journey. Join us in exploring exciting new ways to learn in an effective, personal and more immersive way than ever before. View our new apps in education infographic below. The infographic can also be downloaded via our SlideShare channel. Apps in Education: Discover a new generation of Microsoft tools for education from Microsoft Education UK

Posted by on 28 July 2014 | 4:46 am

[Sample Of July 28] How to break the locked lease of blob storage in Windows Azure

July 28 Sample Download : http://code.msdn.microsoft.com/How-to-break-the-locked-99744bf8 This code snippet shows how to break the locked lease of blob storage in Windows Azure. Windows Azure provides functionality to acquire lock on blobs to avoid concurrent writes to blobs. Sometimes, if the backup fails due to prolonged or sustained network connectivity failure, the backup process may not be able to gain access to the blob and the blob may remain orphaned. This means that the blob cannot be written to or deleted until the lease is released. In this case, you might want to break the lease on a blob and this code snippet is to help you in this regard.   You can find more code samples that demonstrate the most typical programming scenarios by using Microsoft All-In-One Code Framework Sample Browser or Sample Browser Visual Studio extension. They give you the flexibility to search samples, download samples on demand, manage the downloaded samples in a centralized place, and automatically be notified about sample updates. If it is the first time that you hear about Microsoft All-In-One Code Framework, please watch the introduction video on Microsoft Showcase, or read the introduction on our homepage http://1code.codeplex.com/.

Posted by on 28 July 2014 | 4:32 am

Episode 8 – Project Roslyn

Patric Boscolo erklärt in dieser Folge des TechTalk, was es mit dem Roslyn Compiler auf sich hat und warum man sich als Entwickler nicht damit beschäftigen muss, aber es unbedingt will. Mehr vom TechTalk The post Episode 8 – Project Roslyn appeared ...read more...(read more)

Posted by on 28 July 2014 | 3:38 am

More Updates to Azure Mobile Services (Link)

Just posted the blog Azure Mobile Services .NET Updates describing new features now available for Azure Mobile Services including: Support for CORS using ASP.NET Web API CORS enabling first class support for specifying CORS policy at a per-service, per-controller, or per-action level. An extensible authentication model enabling you to control which authentication mechanisms are available for your mobile service clients. For example, you can add your own authentication mechanisms in addition to or in place of the default support for Azure Active Directory, Twitter, Facebook, Google, and Microsoft Account. Support for Azure Active Directory Authentication using a server-side flow simplifying client authentication significantly. If you are building cloud connected mobiles apps then check out Microsoft Azure Mobile Services and let us know what you think! Have fun! Henrik

Posted by on 28 July 2014 | 3:34 am

TechTalk Episode 5: Kinect für Windows

In der 5. Folge des TechTalk sprechen Gunter und Oliver über die neue Kinect für Windows. Die neue Kinect verfügt über viele Verbesserungen gegenüber der ersten Version. Gunter stellt auch das neue SDK für die Kinect vor, das auch für Entwickler noch ...read more...(read more)

Posted by on 28 July 2014 | 3:29 am

プログラミング Windows 第6版 第3章 WPF編

この記事では、「プログラミング Windows 第6版」を使って WPF XAML の学習を支援することを目的にしています。この目的から、書籍と併せて読まれることをお勧めします。 第3章 基本的なイベント処理 3.1(P75) タップ イベント この節では、タッチ、マウス、ペンによるイベントに基本的な事項を説明しています。特に、タッチ系のイベントに関して WinRT XAML と WPF XAML では異なるので注意が必要です。 タッチ、マウス、ペンによる入力は、名前が Pointer で始まる 8 つのイベントにまとめられています(書籍より引用)。 WPF XAML では、Mouse で始まる 10 個のイベントになっており、Pointer で始まるイベントはありません。 複数の指を使った入力は、名前が Manipulation で始まる 5 つのイベントにまとまれています(書籍より引用)。 WPF XAML でも基本は同じで Manipulation で始まるイベントになっており、Win RT XAML の 5つに加えて、ManipulationboundaryFeedback イベントが追加されています。 キーボード入力は、WinRT XAML も WPF XAML も同じで名前が Key で始まる 2つのイベントにまとめられています。 この他に、Tapped、DoubleTapped、RightTapped、Holding というより高度なイベントがあります(書籍より引用)。 WPF XAML では、Tapped イベントはサポートされていないので注意が必要です。 WPF XAML のタッチに関するイベントは、名前が Touch で始まる 5 つのイベントにまとめられています(WinRT XAML は、名前が Touch で始まるイベントはありません)。ここで、WinRT XAML と WPF XAML におけるタッチ サポートの違いを理解しておくことが重要です。 複数の指を使ったジェスチャー操作は、WinRT XAML と WPF XAML は 名前が Manipulation で始まるイベントになっています。 WinRT XAML でタッチの低レベル操作を扱う時は、名前が Pointer で始まるイベントを使用します(タッチ、マウスで共通です)。 WPF XAML でタッチ固有の処理を行う時は、名前が Touch で始まるイベントを使用します。 WPF XAML でタッチとマウスを区別しないでポインターに関する操作を行う時は、名前が Mouse で始まるイベントを使用します。 タップなどの Windows のタッチ操作を直接的に処理できるのは、WinRT XAML となります。つまり、イベントが用意されているという意味になります。 WPF XAML では、名前が Touch で始まるイベントを使って自分でタップなどの操作を実���する必要があります。もちろん、タップなどのタッチ 操作を判定するコンポーネントが市販されていれば、そのようなコンポーネントを使っても良いでしょう。 Windows OS は、OS 側の機能として タッチ 入力をマウス入力と見做して処理できるようになっています。これを、タッチ操作として処理するには Windows Touch API を使用する必要があります。この Windows Touch サポートを盛り込んだのが、WPF XAML におけるタッチ サポートになります。一方で、WinRT XAML は Windows のタッチ操作を提示しているようにタッチ操作を前提に用意された環境だと言えます。 余談になりますが、Windows Touch API サポートは Windows 7 からになります。Windows Vista では、テーブル型のマルチタッチ コンピューターの Surface のための独自拡張になっていました。もちろん、Silverlight もタッチ サポートが入りましたが、名前が Touch で始まるイベントのみのサポートになっており、Windows Phone 向けの Silverlight で DoubleTap のサポートが追加されています。 タッチの違いが理解できれば、TapTextBlock サンプルをどのように書き換えれば良いかが理解できたことでしょう(もちろん、第1章などで説明した、Page をWindows へ、組み込みスタイルの変更なども必要です)。それでは、MainWindow.xaml の抜粋を示します。 <Grid> <TextBlock Name="txtblk" Text="Touch Text!" FontSize="96" HorizontalAlignment="Center" VerticalAlignment="Center" TouchDown="txtblk_TouchDown" /> </Grid>   TouchDown イベントに書き換えていますが、もちろん TouchUp イベントでも構いません。要は、どのタイミングでコードを実行するかという違いだからです。それでは、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { Random rand = new Random(); byte[] rgb = new byte[3]; public MainWindow() { InitializeComponent(); } private void txtblk_TouchDown(object sender, TouchEventArgs e) { rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); txtblk.Foreground = new SolidColorBrush(clr); } }   3.2(P79) ルーティング イベントの処理 この節では、ルーティング イベントを説明しています。ルーティング イベントは、WPF XAML でも同じ機能となります。一方で Windows Forms には、無い考え方になります。あえて Windows Forms に当てはめるのであれば、たとえば KeyDown イベントに対する PreviewKeyDown イベントが全てのイベントでサポートされていると考えることができます。ルーティング イベントは、別名としてバブル イベントと呼ばれています。何故、バブルかと言えば、XAML 定義の中でイベントが発生したら タグを親に向かって連鎖的にイベントを発生させることができるからです(つまり、泡が広がるのと同じです)。それでは、RoutedEvents0 プロジェクトの Mainwindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { Random rand = new Random(); byte[] rgb = new byte[3]; public MainWindow() { InitializeComponent(); } private void TextBlock_TouchDown(object sender, TouchEventArgs e) { TextBlock txtblk = sender as TextBlock; rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); txtblk.Foreground = new SolidColorBrush(clr); } }   TextBlock_TouchDown イベントを呼び出す MainWindow.xaml の抜粋を示します。 <Window x:Class="RoutedEvents0.MainWindow" ... FontSize="48"> <Grid> <TextBlock Text="Left / Top" HorizontalAlignment="Left" VerticalAlignment="Top" TouchDown="TextBlock_TouchDown" /> ... <TextBlock Text="Right / Bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" TouchDown="TextBlock_TouchDown" /> </Grid> </Window>   実行結果は、同じように TextBlock をタッチすることで色が変化するようになります。 次の RoutedEvents1 プロジェクトでは、ルーティング イベントを理解するために TextBlock ではなく、Grid にイベントを設定します。 <Grid TouchDown="Grid_TouchDown"> <TextBlock Text="Left / Top" HorizontalAlignment="Left" VerticalAlignment="Top" /> ... <TextBlock Text="Right / Bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" /> </Grid> そして、RoutedEvents1 プロジェクトの MainWindow.xaml.cs の抜粋を示します。 private void Grid_TouchDown(object sender, TouchEventArgs e) { if (e.OriginalSource is TextBlock) { TextBlock txtblk = e.OriginalSource as TextBlock; rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); txtblk.Foreground = new SolidColorBrush(clr); } } イベント ハンドラーのコードは、WinRT XAML と同じだということがわかります。 今度は、XAML でイベントを定義しない RoutedEvents2 プロジェクトの MainWindow.xaml の抜粋を示します。 <Window x:Class="RoutedEvents2.MainWindow" ... FontSize="48"> <Grid> <TextBlock Text="Left / Top" HorizontalAlignment="Left" VerticalAlignment="Top" /> ... <TextBlock Text="Right / Bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" /> </Grid> </Window>   イベントの定義を示すために、MainWindow.xaml.cs の抜粋を示します。 protected override void OnTouchDown(TouchEventArgs e) { if (e.OriginalSource is TextBlock) { TextBlock txtblk = e.OriginalSource as TextBlock; rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); txtblk.Foreground = new SolidColorBrush(clr); } base.OnTouchDown(e); }   WinRT XAML と同じように、OnTouchDown イベントをオーバーライドすることでイベントを処理しています。 今度は、イベント引数の OriginalSource のオブジェクトによって、色を変える RoutedEvents3 プロジェクトの MainWindow.xaml.cs の抜粋を示します。 protected override void OnTouchDown(TouchEventArgs e) { rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); SolidColorBrush brush = new SolidColorBrush(clr); if (e.OriginalSource is TextBlock) (e.OriginalSource as TextBlock).Foreground = brush; else if (e.OriginalSource is Grid) (e.OriginalSource as Grid).Background = brush; base.OnTouchDown(e); }   また、RoutedEvents3 プロジェクトの MainWindow.xaml の抜粋を示します。 <Grid Background="White"> <TextBlock Text="Left / Top" HorizontalAlignment="Left" VerticalAlignment="Top" /> ... <TextBlock Text="Right / Bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" /> </Grid> ここで注意して欲しいのが、Grid 要素の Background プロパティを「White」に指定している点です。コードでは、OriginalSource によって TextBlock か Grid かを識別して背景色を変更していますが、Grid の Background プロパティを指定しないと「Background="{x:Null}"」を指定したことと同義になり、Grid コントロールが不可視となり、イベントを発生させることができなくなります。これは、XAML を使った UI 技術の特徴にもなります。WinRT XAML でこのことが問題にならないのは、Background に組み込みのスタイルを指定しているからです。  RoutedEvents3 から、Grid の背景色と TextBlock の背景色をイベントによってランダムに設定するようにした RoutedEvents4 の MainWindow.xaml の抜粋を示します。 <Grid Name="contentGrid"> <TextBlock Text="Left / Top" HorizontalAlignment="Left" VerticalAlignment="Top" TouchDown="TextBlock_TouchDown" /> ... <TextBlock Text="Right / Bottom" HorizontalAlignment="Right" VerticalAlignment="Bottom" TouchDown="TextBlock_TouchDown" /> </Grid>   そして、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { Random rand = new Random(); byte[] rgb = new byte[3]; public MainWindow() { InitializeComponent(); } private void TextBlock_TouchDown(object sender, TouchEventArgs e) { TextBlock txtblk = sender as TextBlock; txtblk.Foreground = GetRandomBrush(); } protected override void OnTouchDown(TouchEventArgs e) { contentGrid.Background = GetRandomBrush(); base.OnTouchDown(e); } Brush GetRandomBrush() { rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); return new SolidColorBrush(clr); } } RoutedEvents4 プロジェクトでは、RoutedEvents3 プロジェクトと異なり Grid 要素の Background プロパティを指定していません。それでも、RoutedEvents3 プロジェクトと同じように動作する理由は、OnTouchDown イベントにあります。このイベントで、無条件に Grid の背景色を変更しているから問題なく動作します。このことは、RoutedEvents3 プロジェクトの説明と合わせると、次に示す特徴を表しています。 TouchEventArgs.OriginalSource には、背景色が Null な Grid オブジェクトが含まれない。 OnTouchDown イベントは、Window オブジェクトをオーバーライドしているので必ず発生する。 次のサンプルでは、バブル イベントという性格を持つルーティング イベントを停止するかどうかを試します。では、RoutredEvents5 プロジェクトの MainWindow.xaml.cs  の抜粋を示します。 private void TextBlock_TouchDown(object sender, TouchEventArgs e) { TextBlock txtblk = sender as TextBlock; txtblk.Foreground = GetRandomBrush(); e.Handled = true; } イベント引数が持つ Handled プロパティを設定しているだけで、Handled プロパティの説明は次の節で紹介しています。 3.3(P85) Handled 設定の上書き この節で最初に説明する RoutedEvents6 プロジェクトでは、Grid要素の背景色を変更するイベントと TextBlock の色を変更するイベントを定義しています。この MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { Random rand = new Random(); byte[] rgb = new byte[3]; public MainWindow() { InitializeComponent(); this.AddHandler(UIElement.TouchDownEvent, new EventHandler(OnWindowTouchDown), true); } private void TextBlock_TouchDown(object sender, TouchEventArgs e) { TextBlock txtblk = sender as TextBlock; txtblk.Foreground = GetRandomBrush(); e.Handled = true; } private void OnWindowTouchDown(object sender, TouchEventArgs e) { contentGrid.Background = GetRandomBrush(); } Brush GetRandomBrush() { rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); return new SolidColorBrush(clr); } } コンストラクターで行っているイベント ハンドラーの登録は、WinRT XAML と同じように AddHandler メソッドを使用しています。AddHandler メソッドを使用している理由は、本書を読んで確認してください。 3.4(P87) 入力、位置合わせ、背景 この節では、RoutedEventns3 と比較して TextBlock がどのように配置されるかを ToutedEvents7 プロジェクトを使って説明しています。それでは、MainWindow.xaml の抜粋を示します。 <Window x:Class="RoutedEvents7.MainWindow" ... FontSize="48"> <Grid Background="White"> >TextBlock Text="Hello, Windows 8!" Foreground="Red" /> </Grid> </Window> そして、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { Random rand = new Random(); byte[] rgb = new byte[3]; public MainWindow() { InitializeComponent(); } protected override void OnTouchDown(TouchEventArgs e) { rand.NextBytes(rgb); Color clr = Color.FromArgb(255, rgb[0], rgb[1], rgb[2]); SolidColorBrush brush = new SolidColorBrush(clr); if (e.OriginalSource is TextBlock) (e.OriginalSource as TextBlock).Foreground = brush; else if (e.OriginalSource is Grid) (e.OriginalSource as Grid).Background = brush; base.OnTouchDown(e); } } もちろん。RoutedEvents3 プロジェクトと同じように Grid 要素の Background プロパティを設定しています。実行結果を示します。 自分で実行して、ウィンドウをタップしてみるとわかりますが、ウィンドウのどこをタップしても TextBlock の色が変化されます。つまり、TextBlock の表示位置などの指定していないので、ウィンドウ一杯の領域が TextBlock と扱われて、OnTouchDown イベント ハンドラーの Grid を判定するロジックが動作しないことを確認できます。この問題を解決するには、書籍に記述されているように TextBlock の表示位置や表示サイズを指定して、Grid の背景色に何かの色(たとえば、Whiteなど)を指定するか、「Transparent」を指定することになります(Transparent と Null は異なりますので、注意してください)。 3.5(P90) サイズと向きの変更 この節では、Windows ストア アプリが画面の向きやサイズ変更にどのように対応しているかをサンプルを使って説明しています。最初に説明しているのは、WhatSize プロジェクトを使って、画面サイズを確認することです。それでは、WhatSize プロジェクトの MainWindow.xaml の抜粋を示します。 <Window x:Class="WhatSize.MainWindow" ... SizeChanged="Window_SizeChanged"> <Grid> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top"> ↤ <Run x:Name="widthText" /> pixels ↦ </TextBlock> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center"> ↥ <LineBreak /> <Run x:Name="heightText" /> pixels <LineBreak /> ↧ </TextBlock> </Grid> </Window>   続いて、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_SizeChanged(object sender, SizeChangedEventArgs e) { widthText.Text = e.NewSize.Width.ToString(); heightText.Text = e.NewSize.Height.ToString(); } }   WinRT XAML と同じように SizeChanged イベントを処理することで、画面のサイズを取得することができます。 書籍では、続いて、画面の向きが変化したかどうかを ScalableInternationalHelloWorld プロジェクトを使って説明しています。この時に使用しているクラスが、DisplayProperties (Windows 8.1では、DisplayInformation) になりますが、このクラスは Windows Runtime 固有であり、WPF などのデスクトップ アプリから使用することはできません。 それでは、WPF などのデスクトップ向けのアプリでタブレット PC 固有の画面の向きに対応するにはどうしたら良いでしょうか。これには、いつかの手段を考えることができます。 システム イベントの DisplaySettingsChanged イベントで処理する(もしくは、WM_DISPLAYCHANGED メッセージを ウィンドウ プロシージャで処理します)。 Screen クラスの PrimaryScreent プロパティを使って、Bounds プロパティ経由で縦横を比較して画面の向きを処理する。 これらの説明が、「Detecting Screen Orientation and Screen Rotation in Tablet PC Applications」という ドキュメントに記載されていますので、必要に応じて処理する必要があります。よって、 ScalableInternationalHelloWorld プロジェクトはサンプルに含まれていません。 Windows ストア アプリでは、画面の向きやスケーリングを完全にサポートしています。一方で、デスクトップ上のアプリは WPFのみがスケーリングのに対応し、画面の向きなどの対応はアプリケーションに任せるという考え方になっている点にご注意ください。 3.6(P95) Run でのバインディング この節で最初に説明している TextBlock 内に「<Run Text="{Binding ElementName=window, Path=ActualWidth}" />」という記述方法を WPF XAML で行うと、Visual Studio 2013 の IDE は警告を表示します。警告を無視して実行すると、実行時に初回例外が発生します。この動きは、WinRT XAML とは違いますが、Run 要素を使わないバインディングでは正常に動作します。 <Window x:Class="WhatSizeBinding.MainWindow" ... x:Name="window" FontSize="36"> <Grid> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="{Binding ElementName=window, Path=ActualWidth}" /> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Text="{Binding ElementName=window, Path=ActualHeight}" /> </Grid> </Window>   実行結果も書籍と同じようになります。なぜ、Run 要素にバインディングができないかの理由は書籍を読めば答えがわかるようになっています。ここでは、WinRT XAML と WPF XAML の挙動の違いを説明するだけにします。 3.7(P98) タイマーとアニメーション この節では、DispatcherTimer クラスを使った説明になります。DispatcherTimer クラスは、XAML という UI 技術を使った場合に使える共通のタイマー クラスとなっています。一方 Windows Forms では、System.Windows.Forms.Timer クラスが用意されていて、デザイナーにツールボックスからドラッグ&ドロップして使用することができますが、WPF を初めとする XAML 系の UI 技術ではデザイナー サポートは用意されていません。つまり、タイマーを使用したい場合は、自分でコードを記述する必要がある点にご注意ください。 最初に DigitalClock プロジェクトの MainWindow.xaml の抜粋を示します。 <Grid> <TextBlock Name="txtblk" FontFamily="Lucida Console" FontSize="120" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid>   xaml は WinRT と同じであり、分離コードも同じになります。次にMainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += OnTimerTick; timer.Start(); } void OnTimerTick(object sender, object e) { txtblk.Text = DateTime.Now.ToString("h:mm:ss tt"); } } もちろん、実行した結果も同じになります。 次のサンプルは、CompositionTarget.Rendering イベント ハンドラーを利用した ExpandingText プロジェクトになります。MainWindow.xaml の抜粋を示します。 <Grid> <TextBlock Name="txtblk" Text="Hello, Windows 8!" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> ExpandingText プロジェクトは、WPF でも同じコードを使用できますので、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); CompositionTarget.Rendering += OnCompositionTargetRendering; } void OnCompositionTargetRendering(object sender, object args) { RenderingEventArgs renderArgs = args as RenderingEventArgs; double t = (0.25 * renderArgs.RenderingTime.TotalSeconds) % 1; double scale = t < 0.5 ? 2 * t : 2 - 2 * t; txtblk.FontSize = 1 + scale * 143; } } このコードで WinRT XAML と同じように フォント サイズが変化するアニメーションになります。 今度は、色をアニメーション化する ManualBrushAnimation プロジェクトの MainWindow.xaml の抜粋を示します。 <Grid Name="contentGrid"> <TextBlock Name="txtblk" Text="Hello, Windows 8!" FontFamily="Times New Roman" FontSize="96" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> 色に基づいてアニメーションするコードも同じになります。MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); CompositionTarget.Rendering += OnCompositionTargetRendering; } void OnCompositionTargetRendering(object sender, object args) { RenderingEventArgs renderingArgs = args as RenderingEventArgs; double t = (0.25 * renderingArgs.RenderingTime.TotalSeconds) % 1; t = t < 0.5 ? 2 * t : 2 - 2 * t; // Background byte gray = (byte)(255 * t); Color clr = Color.FromArgb(255, gray, gray, gray); contentGrid.Background = new SolidColorBrush(clr); // Foreground gray = (byte)(255 - gray); clr = Color.FromArgb(255, gray, gray, gray); txtblk.Foreground = new SolidColorBrush(clr); } } 今度は、 SolidColorBrush をコードではなく XAML で定義した ManualColorAnimation プロジェクトになります。MainWindow.xaml の抜粋を示します。 <Grid> <Grid.Background> <SolidColorBrush x:Name="gridBrush" /> </Grid.Background> <TextBlock Text="Hello, Windows 8!" FontFamily="Times New Roman" FontSize="96" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock.Foreground> <SolidColorBrush x:Name="txtblkBrush" /> </TextBlock.Foreground> </TextBlock> </Grid> この XAML を使用する MainWindow.xaml.cs の抜粋を示します。 void OnCompositionTargetRendering(object sender, object args) { RenderingEventArgs renderingArgs = args as RenderingEventArgs; double t = (0.25 * renderingArgs.RenderingTime.TotalSeconds) % 1; t = t < 0.5 ? 2 * t : 2 - 2 * t; // Background byte gray = (byte)(255 * t); gridBrush.Color = Color.FromArgb(255, gray, gray, gray); // Foreground gray = (byte)(255 - gray); txtblkBrush.Color = Color.FromArgb(255, gray, gray, gray); } もちろん、WPF でも WinRT XAML と同じように動作します。 最後に扱うサンプルは、虹色に変化するアニメーションである RainbowEight プロジェクトになります。最初に、MainWindow.xaml の抜粋を示します。 <Grid> <TextBlock Name="txtblk" Text="8" FontFamily="CooperBlack" FontSize="1" HorizontalAlignment="Center"> <TextBlock.Foreground> <LinearGradientBrush x:Name="gradientBrush"> <GradientStop Offset="0.00" Color="Red" /> <GradientStop Offset="0.14" Color="Orange" /> <GradientStop Offset="0.28" Color="Yellow" /> <GradientStop Offset="0.43" Color="Green" /> <GradientStop Offset="0.57" Color="Blue" /> <GradientStop Offset="0.71" Color="Indigo" /> <GradientStop Offset="0.86" Color="Violet" /> <GradientStop Offset="1.00" Color="Red" /> <GradientStop Offset="1.14" Color="Orange" /> <GradientStop Offset="1.28" Color="Yellow" /> <GradientStop Offset="1.43" Color="Green" /> <GradientStop Offset="1.57" Color="Blue" /> <GradientStop Offset="1.71" Color="Indigo" /> <GradientStop Offset="1.86" Color="Violet" /> <GradientStop Offset="2.00" Color="Red" /> </LinearGradientBrush> </TextBlock.Foreground> </TextBlock> </Grid> WinRT XAML との違いは、何もありません。TextBlock 要素に LinearGridentBrush を設定していることも同じです(このブラシが、虹色に変化する雰囲気を醸し出します)。それでは、MainWindow.xaml.cs の抜粋を示します。 public partial class MainWindow : Window { double txtblkBaseSize; // ie, for 1-pixel FontSize public MainWindow() { InitializeComponent(); Loaded += MainWindow_Loaded; } void MainWindow_Loaded(object sender, RoutedEventArgs e) { //txtblkBaseSize = txtblk.ActualHeight; // ActualHeight が異なるため txtblkBaseSize = txtblk.DesiredSize.Height; CompositionTarget.Rendering += OnCompositionTargetRendering; } void OnCompositionTargetRendering(object sender, object args) { // Set FontSize as large as it can be txtblk.FontSize = this.ActualHeight / txtblkBaseSize; // Calculate t from 0 to 1 repetitively RenderingEventArgs renderingArgs = args as RenderingEventArgs; double t = (0.25 * renderingArgs.RenderingTime.TotalSeconds) % 1; // Loop through GradientStop objects for (int index = 0; index < gradientBrush.GradientStops.Count; index++) gradientBrush.GradientStops[index].Offset = index / 7.0 - t; } } コメントを記述していることから違いを理解できると思いますが、WPF XAML では、このようなケースでは ActualHeight を使用するのは望ましくありません。このため、DesiredSize プロパティを使用して描画しようとするサイズを取得しています。DesiredSize プロパティは、レイアウトを描画する時の必要な描画サイズを計算した値になります。WinRT XAML では、ActualHeight プロパティで問題ないことから、WPF で ConpositionTarget.Rendering イベントで オブジェクトの描画サイズにアクセスするには、DesiredSize を使用すると覚えていただければ結構です。実行結果を示します。 ここまで説明してた違いを意識しながら、第3章を読むことで WPF にも書籍の内容を応用することができるようになることでしょう。

Posted by on 28 July 2014 | 2:21 am

Small Basic Game Programming - Separation Between Data And Procedure

Last week, I introduced a text adventure game.  If I expand the game story of that manner as in the program, the program will have a lot of If statements and Goto statements.   Today, I will introduce rewritten program with less If and Goto statements.  The updated version is published as FCD758-1, Main Main part of this program became very simple. 1.' Text Adventure 0.2 2.' Program ID FCD758-1 3.Init() 4.Game() 5.' end of program Initialization for Scenario Data This data is like a main program of the previous text adventure program introduced last week.  So, this data is a kind of script language.  The grammar of this scenario data is: A line started with " " (space) is displayed as a text. A line ended with ":" (colon)  is treated as a label targeted by jump control statements. A line started with "->" is treated as a jump (like Goto) control statement.  A jump with single label is non conditional.  A jump with several labels is conditional. A line other than above and has "," (comma) is displayed as options and prompts user selection. Game scenario ends at scenario[21] (line 32).  But for testing, I added scenario[22] (line 33) to loop back to the top. 6.Sub Init 7.  scenario[1] = "stage_0:" 8.  scenario[2] = " You're at a fork in the road." 9.  scenario[3] = " Which way do you go?" 10.  scenario[4] = "LEFT,RIGHT,STAY" 11.  scenario[5] = "-> stage_1_1,stage_1_2,stage_1_3,stage_0" 12.    13.  scenario[6] = "stage_1_1:" 14.  scenario[7] = " Good choice, you find some money. :)" 15.  scenario[8] = " Have a nice day." 16.  scenario[9] = "-> end" 17.    18.  scenario[10] = "stage_1_2:" 19.  scenario[11] = " You're at a stairs." 20.  scenario[12] = " Which way do you go?" 21.  scenario[13] = "UP,BACK" 22.  scenario[14] = "-> stage_2,stage_0,stage_1_2" 23.    24.  scenario[15] = "stage_1_3:" 25.  scenario[16] = " Nothing happend." 26.  scenario[17] = " " 27.  scenario[18] = "-> stage_0" 28.    29.  scenario[19] = "stage_2:" 30.  scenario[20] = " Hard choice. But, good luck!" 31.    32.  scenario[21] = "end:" 33.  scenario[22] = "-> stage_0" 34.  nScenario = Array.GetItemCount(scenario) 35.  pScenario = 1 36.EndSub Parsing and Executing the Scenario Subroutine Game parses the scenario and execute each statement. 37.Sub Game 38.  While pScenario <= nScenario 39.    line = scenario[pScenario] 40.    If Text.StartsWith(line, " ") Then 41.      TextWindow.WriteLine(Text.GetSubTextToEnd(line, 2)) 42.      pScenario = pScenario + 1 43.    ElseIf Text.EndsWith(line, ":") Then 44.      pScenario = pScenario + 1 45.    ElseIf Text.StartsWith(line, "->") Then 46.      id = 1 47.      Jump() 48.    ElseIf Text.IsSubText(line, ",") Then 49.      choices = line 50.      Choose() 51.      TextWindow.WriteLine("") 52.      If id = 0 Then 53.        id = n + 1 54.      EndIf 55.      pScenario = pScenario + 1 56.      line = scenario[pScenario] 57.      Jump() 58.    Else 59.      msg = "Unknown scenario: line " + pScenario 60.      Error() 61.    EndIf 62.  EndWhile 63.EndSub Processing for "->" Control Statement "->" statement behaves as Goto statement if it has a single label.  But it has some labels, it behaves like ON GOTO statement in BASIC language.  If the previous line has options, label is selected as the selected option id (1, 2, ...).  If the choice is invalid then the last label is selected. 64.Sub Jump 65.  ' param id - choice 66.  ' param line 67.  ' work label - destination 68.  len = Text.GetLength(line) 69.  p = 3 70.  While p <= len And Text.GetSubText(line, p, 1) = " " 71.    p = p + 1 72.  EndWhile 73.  label = "" 74.  For i = 1 To id 75.    c = Text.GetIndexOf(Text.GetSubTextToEnd(line, p), ",") 76.    If c = 0 Then 77.      c = len - p + 2 78.    EndIf 79.    If i = id Then 80.      label = Text.GetSubText(line, p, c - 1) + ":" 81.    Else 82.      p = p + c 83.      If len < p Then 84.        msg = "Label shortage: line " + pScenario 85.        Error() 86.      EndIf 87.    EndIf 88.  EndFor 89.  For p = 1 To nScenario 90.    If scenario[p] = label Then 91.      pScenario = p 92.      Goto break 93.    EndIf 94.  EndFor 95.  msg = "Label " + label + " not found: line " + pScenario 96.  Error() 97.  break: 98.EndSub Displaying Error If the scenario has error, the program is not to be continued.  So, the program displays error and stops. 99.Sub Error 100.  TextWindow.ForegroundColor = "Red" 101.  TextWindow.WriteLine(msg) 102.  TextWindow.WriteLine("") 103.  TextWindow.ForegroundColor = "Gray" 104.  pScenario = nScenario + 1 105.EndSub And subroutine Choice is the same as the previous text adventure program. With small change, the scenario can be read from a text file.  By today's update, procedures become simple.  But data (scenario) becomes little complex.  Because the scenario is a kind of script, it will be needed testing and debugging.  For this program, there is room for improvement.  But I'm going to write about text window base game program with action next week. Have a happy programming!

Posted by on 28 July 2014 | 2:00 am

メディアのエンコーディング ジョブでの課金対象のデータ量を計算する方法

このポストは、7 月 16 日に投稿した Calculating Billable Gigabytes for Media Encoding Jobs の翻訳です。 Media Services では、メディア プロセッサの 1 つである Azure Media Encoder をタスクで使用し、そのタスクが含まれるジョブを送信した場合に、処理されたデータ量に応じて料金が発生します。Azure 課金ポータルでは、請求期間内に処理されたデータ量の合計をギガバイト単位で確認できますが、ジョブ単位やタスク単位の内訳はわかりません。このブログ記事では、課金対象のデータ量の内訳をジョブ単位およびタスク単位で計算するサンプル コード、およびその計算結果を Excel の Power Query で分析する方法についてご紹介します。 ストレージ内のメディア アセット メディア アセットを作成する場合、Media Services では GUID が生成され、この GUID から、“nb:cid:UUID:” というプレフィックスの後に GUID が続くメディア アセットの ID が作成されます。つまり、メディア アセットの ID は “nb:cid:UUID:<GUID>” という形になります。また Media Services では、指定されたストレージ アカウントに “asset-<GUID>” という名前のコンテナーが作成されます。アセットの作成が完了したら、アセット ファイルをストレージ コンテナーにアップロードできます。エンコーディング タスクを含むジョブを送信した場合、エンコーダーからの出力ファイルは出力されるアセットに関連付けられたストレージ コンテナーに格納されます。 サンプル コード ご紹介するサンプル コードは下記の処理を行います。 指定された Media Services アカウントのジョブをすべてリストにまとめます。 各ジョブのタスクをすべてリストにまとめます。 完了済みタスクについて、入力アセットと出力アセットをすべてリストにまとめます。 各入力アセットおよび出力アセットについて、それぞれのアセットに関連付けられているストレージ コンテナーの BLOB をすべてリストにまとめ、アセットの各 BLOB のサイズを合計してアセットのサイズを計算します。 パーティション キーとしての JobId と、行キーとしての TaskId を含む、JobAndTaskTableEntityという名前の Azure Tables エンティティを作成します。 JobAndTaskTableEntity には、StartTime、EndTime、MediaProcessor、RunningDuration、InputAssetSize、OutputAssetSize などの他のメンバーも含まれます。 さらに、JobAndTaskTableEntity を JobAndTaskMetadata という名前の Azure Tables に書き出します。   サンプル コードの App.Config ファイルは次のようになります。 <?xml version="1.0" encoding="utf-8"?> <configuration>   <startup>     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />   </startup>   <appSettings>     <add key="MediaServicesAccountName" value="<MediaAccountName>" />     <add key="MediaServicesAccountKey" value="<MediaAccountKey>" />     <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<StorageAccountName>;AccountKey=<StorageAccountKey>"/>   </appSettings>   <runtime>     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">       <dependentAssembly>         <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />         <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />       </dependentAssembly>     </assemblyBinding>   </runtime> </configuration> 上の App.Config 内の、<MediaAccountName> および <MediaAccountKey> の部分はお客様の Media Services アカウントの名前とキーに変更してください。また、<StorageAccountName> および <StorageAccountKey> の部分は、Media Services アカウントに関連付けられているストレージ アカウントの名前とキーに変更してください。 サンプル コードは次のとおりです。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; using Microsoft.WindowsAzure.Storage.Table; using Microsoft.WindowsAzure.MediaServices.Client; using System.Configuration;   namespace JobAndTaskBilling {     /// <summary>     ///     /// </summary>     public class JobAndTaskTableEntity : TableEntity     {         public DateTime StartTime { get; set; }         public DateTime EndTime { get; set; }         public string MediaProcessor { get; set; }         public TimeSpan RunningDuration { get; set; }         public Double InputAssetSize { get; set; }         public Double OutputAssetSize { get; set; }     }       /// <summary>     ///     /// </summary>     class Program     {         // App.config ファイルから値を読み込む         private static readonly string _mediaServicesAccountName =             ConfigurationManager.AppSettings["MediaServicesAccountName"];         private static readonly string _mediaServicesAccountKey =             ConfigurationManager.AppSettings["MediaServicesAccountKey"];         private static readonly string _storageConnectionString =             ConfigurationManager.AppSettings["StorageConnectionString"];           //         private static CloudStorageAccount _cloudStorage = null;         private static CloudBlobClient _blobClient = null;           private static CloudTableClient _tableClient = null;         private static CloudTable _taskTable = null;                   private static CloudMediaContext _context = null;         private static MediaServicesCredentials _cachedCredentials = null;           static void Main(string[] args)         {             try             {                 // Media Services の認証情報を静的クラス変数の形で作成しキャッシュする                 _cachedCredentials = new MediaServicesCredentials(_mediaServicesAccountName, _mediaServicesAccountKey);                   // キャッシュされた認証情報から CloudMediaContext を作成する                 _context = new CloudMediaContext(_cachedCredentials);                   // App.Config に含まれているストレージの接続文字列から CloudStorageAccount インスタンスを作成する                 _cloudStorage = CloudStorageAccount.Parse(_storageConnectionString);                   _blobClient = _cloudStorage.CreateCloudBlobClient();   // CloudBlobClient インスタンスを作成して BLOB 操作を行う                 _tableClient = _cloudStorage.CreateCloudTableClient(); // CloudTableClient インスタンスを作成してテーブル操作を行う                   _taskTable = _tableClient.GetTableReference("JobAndTaskMetadata");                 _taskTable.CreateIfNotExists();  // JobAndTaskMetadata が未作成の場合は作成する                   ProcessJobs();             }             catch (Exception ex)             {                 Console.WriteLine(ex.Message);             }         }           /// <summary>         /// この関数では、Media Services アカウントのすべてのジョブをループ処理する         /// </summary>         static void ProcessJobs()         {             try             {                 Dictionary<string, string> _dictMPs = GetMediaProcessors();                   int skipSize = 0;                 int batchSize = 1000;                 int currentBatch = 0;                                  while (true)                 {                 // Media Services アカウントのすべてのジョブをループ処理する (1 回あたり 1,000 個)                     IQueryable _jobsCollectionQuery = _context.Jobs.Skip(skipSize).Take(batchSize);                     foreach (IJob job in _jobsCollectionQuery)                     {                         currentBatch++;                         Console.WriteLine("Processing Job Id:" + job.Id);                           ProcessTasks(job, _dictMPs);                     }                       if (currentBatch == batchSize)                     {                         skipSize += batchSize;                         currentBatch = 0;                     }                     else                     {                         break;                     }                                    }             }             catch (Exception ex)             {                 Console.WriteLine(ex.Message);             }         }           /// <summary>         /// Media Services アカウントで使用可能なすべてのメディア プロセッサのリストを作成し、キーが MediaProcessorId、値が MediaProcessorName の辞書を作成する         /// </summary>         /// <returns></returns>         static Dictionary<string, string> GetMediaProcessors()         {             Dictionary<string, string> _dictMPs = new Dictionary<string, string>();             foreach (IMediaProcessor mp in _context.MediaProcessors)             {                 _dictMPs.Add(mp.Id, mp.Name);                            }               return _dictMPs;         }           /// <summary>         /// この関数では、ジョブに関連付けられているすべてのタスクをループ処理する         /// すべての完了済みタスクについて、入力アセットおよび出力アセットのサイズを計算し JobsAndTasksMetadata テーブルにエンティティを書き出す         /// </summary>         /// <param name="job"></param>         static void ProcessTasks(IJob job, Dictionary<string, string> _dictMPs)         {             try             {                 foreach (ITask task in job.Tasks)                 {                     Console.WriteLine("Processing Task Id:" + task.Id);                       // タスクに関連付けられている HistoricalEvents をループ処理して、完了済みタスクを検出する                     // Task.State の状態はすべて Completed であり、これを利用してタスクがエラーで終了したか正常に完了したかを判断することはできない                     for (int i = 0; i < task.HistoricalEvents.Count; i++)                     {                         if (task.HistoricalEvents[i].Code == "Finished")                         {                             try                             {                                 JobAndTaskTableEntity tme = new JobAndTaskTableEntity();                                 tme.PartitionKey = job.Id;                                 tme.RowKey = task.Id;                                 tme.StartTime = Convert.ToDateTime(task.StartTime);                                 tme.EndTime = Convert.ToDateTime(task.EndTime);                                 tme.MediaProcessor = _dictMPs[task.MediaProcessorId]; // MediaProcessor 辞書を使用して MediaProcessorName を特定する                                 tme.RunningDuration = task.RunningDuration;                                 tme.InputAssetSize = 0;                                 tme.OutputAssetSize = 0;                                   for (int j = 0; j < task.InputAssets.Count; j++)                                 {                                     tme.InputAssetSize += GetAssetSize(task.InputAssets[j]);                                 }                                   for (int k = 0; k < task.OutputAssets.Count; k++)                                 {                                     tme.OutputAssetSize += GetAssetSize(task.OutputAssets[k]);                                 }                                   TableOperation op = TableOperation.Insert(tme);                                 _taskTable.Execute(op);                             }                             catch (Exception x)                             {                                 Console.WriteLine(x.Message);                             }                         }                     }                 }             }             catch (Exception ex)             {                 Console.WriteLine(ex.Message);             }         }           /// <summary>         /// アセット コンテナー内のすべての BLOB のリストを作成して各 BLOB のサイズを合計し、アセットのサイズを取得する         /// </summary>         /// <param name="_asset"></param>         /// <returns></returns>         static double GetAssetSize(IAsset _asset)         {             double _assetSize = 0;               try             {                 // アセット コンテナーの名前はアセットの GUID に "asset-" というプレフィックスを追加した文字列。アセットの ID はそのアセットの GUID に "nb:cid:UUID:" というプレフィックスを追加したもの。                 foreach (CloudBlockBlob _blobItem in _blobClient.ListBlobs("asset-" + _asset.Id.Replace("nb:cid:UUID:", "") + "/", true))                 {                     _assetSize += _blobItem.Properties.Length;                 }             }             catch (Exception ex)             {                 // ストレージ内にアセットが存在しない場合はアセットのサイズとして 0 が返される                 // タスクが完了した後でサンプル コードが実行される前にアセットが削除されると、この状況が発生する可能性がある                 Console.WriteLine(ex.Message);             }               return _assetSize;         }              } } このコードで使用されている関数について簡単に説明します。 ProcessJobs この関数は、指定された Media Services アカウントのすべてのジョブをループ処理します。Media Services は、ジョブ コレクションで 1,000 個のジョブを返します。この関数では、Skip および Take を使用して、アカウント内に 1,000 個以上のジョブが存在する場合にも確実にすべてのジョブをリストに含めます。 GetMediaProcessors この関数は、指定された Media Services アカウントで使用可能なすべてのメディア プロセッサをループ処理し、キーが MediaProcesssorId、値が MediaProcessorName の辞書を作成します。この辞書は、JobAndTaskMetadata テーブルにエンティティを書き出すときに使用されます。 ProcessTasks この関数は、特定のジョブに関連付けられているすべてのタスクをループ処理します。さらに、タスクに関連付けられている過去のイベントをすべてループ処理し、タスクが正常に完了したかどうかを確認します。これにより、エラーで終了したタスク (課金対象外) がエントリのログに記録されないようにします。また、完了済みタスクについて入力アセットと出力アセットのサイズを取得し、JobAndTaskMetadata テーブルのエンティティを作成します。 GetAssetSize この関数は、ストレージ アカウントのアセット コンテナー内の BLOB をすべてループ処理し、アセットのサイズをバイト単位で計算します。 Excel の Power Query を使用してデータを分析する 上記のサンプル コードの実行が完了すると、完了済みタスクのデータについてまとめられた、JobAndTaskMetadata という名前の Azure Tables が作成されます。このデータは、Excel の Power Query を使用すると Excel にインポートして分析することができます。Excel の Power Query を使用したことのないお客様は、Microsoft Power Query for Excel のダウンロード ページ (英語) からダウンロードしてご利用ください。インストール完了後に Excel を起動すると、[POWER QUERY] というタブが表示されます。このタブをクリックし、続いて [From Other Sources] ボタンをクリックすると、次のスクリーンショットのように [From Windows Azure Table Storage] というメニュー項目 (下のスクリーンショット参照) が表示されます。 このメニュー項目を選択すると、次のダイアログ ボックスが表示されます。 ストレージ アカウント名を入力すると、次のダイアログが表示されます。 アカウント キーを入力して [Save] をクリックすると、右側に [Navigator] ウィンドウが表示されます。ストレージ アカウントのすべての Azure Tables のリストが表示され、JobAndTaskMetadata テーブルをダブル クリックすると、次のスクリーンショットのように新しいウィンドウが表示されます。 [Content] 列の隣のボタンをクリックすると、次のようなポップアップが表示されます。 そのまま [OK] をクリックすると、すべての列が読み込まれます。上部にある [Apply & Close] ボタンをクリックして、すべてのデータをワークシートに読み込みます。 ここで [Billable Gigabytes] という列を追加し、バイト単位で表示されているアセットのサイズをギガバイト単位に変更するため、InputAssetSize と OutputAssetSize の和を (1024*1024*1024) で割った値を求める式を追加します。Media Services ではメディア プロセッサが「Microsoft Azure Media Encoder」により送信されたタスクのみが課金対象であるため、それ以外の行はフィルターで除外します。 考慮事項 最後に、アプリケーションでサンプル コードを利用する際の注意事項について説明します。 MSDN の「クォータと制限」のページに記載されているように、Media Services アカウントではジョブ、アセット、およびタスクの最大数に制限が設けられています。ここでご紹介したサンプル コードは、指定された Media Services アカウントでアセット、ジョブ、およびタスクが削除されていないことを前提としています。しかし、アプリケーションが多数のジョブを送信する場合は、これらを削除しないままにすることは困難です。このような場合には、ジョブやアセットを削除する直前で上記のコードの ProcessTasks 関数を使用することを推奨します。 アプリケーションが、ジョブ完了後にアセット コンテナーでメディアの BLOB を追加または削除すると、正確な課金対象のデータ量が得られません。これを防ぐために、ジョブが完了したらすぐにそのジョブに対して ProcessTasks 関数を実行することを推奨します。ジョブ通知を使用している場合は、ジョブの状態が “Finished” になったことを示すメッセージを受け取ったらすぐに ProcessTasks 関数を呼び出すことができます。 この記事でご紹介したサンプル コードは、すべてのアセットが 1 つのストレージ アカウントに含まれている Media Services アカウントで使用することを前提としていますが、簡単な変更で複数のストレージ アカウントでも動作するようにできます。 この記事のサンプル コードでは、InputAssetSize と OutputAssetSize はバイト単位の値を書き出します。このコードがギガバイト単位の値を書き出すように変更することもできますし、さらに JobAndTaskMetadata テーブルに新しい列を追加して InputAssetSize と OutputAssetSize の合計を書き出すことも可能です。 JobAndTaskMetadata テーブルのデータを表示するには、Microsoft Azure 用の各種エクスプローラーのうち Azure Tables をサポートしている既存のものを使用する方法と、Excel を使用する方法があります。Excel では、ピボット テーブルなどの強力なデータ操作機能を使用できるので、データを詳細に分析することができます。 毎月の Azure の料金請求は、請求の応答日およびアカウントに適用される割引 (大口値引きやコミットメント割引) に基づいて計算されます。この記事のサンプル コードの結果と Azure の月間請求額を比較する場合はこの点にご注意ください。 この記事のサンプル コードには、副次的な効果として、Media Encoder 以外のメディア プロセッサで処理されたデータ量をワークシートに読み込まれたデータから確認できます。

Posted by on 28 July 2014 | 2:00 am

ASP.NET の開発者が Azure Mobile Services に関心を持つべき理由

このポストは、7 月 11 日に投稿した Azure Mobile Services: why should ASP.NET developers care? の翻訳です。 Azure Mobile Services (英語) では、モバイル開発者は、クラウドでホストされたバックエンドをターンキー型の手法でアプリに追加できます。現在このサービスは、ASP.NET Web API を使用したバックエンド ロジックの記述を完全にサポートしています。Mobile Services には、ASP.NET でモバイル対応の API を構築する開発者向けに、次のような魅力的な機能が用意されています。 クライアント SDK による、あらゆるモバイル プラットフォームで利用できるターンキー バックエンド: Mobile Services では、すべての機能を備えたバックエンドを iOS、Android、Windows、Windows Phone、または HTML アプリにすばやく追加できます。また、Xamarin、Sencha、PhoneGap などのクロスプラットフォームのフレームワークを使用することも可能です。これらの各プラットフォームに対応するクライアント SDK が提供されているので、開発者はクラウドでホストされたバックエンドに各自のアプリケーションを簡単に接続できます。 ご利用のモバイル API に適したトップ クラスのホスティング: Mobile Services は Web API を使用して構築され、開発者はあらゆる Web API コントローラーをサービスに公開できます。Mobile Services と他のコンピューティング環境との違いは、マイクロソフトがお客様に代わって Web API コントローラーを監視および管理していることです。Web API ランタイムまたは拡張機能に問題があれば、マイクロソフトが修正プログラムを適用するので心配はご無用です。また、問題がお客様のコントローラーのコードに関係すると考えられる場合はご連絡いたします。 高付加価値のモバイル バックエンド機能: Mobile Services には、数多くの機能がありますが、これらの機能はお客様の Web API ですぐにご利用いただけます。機能の例として、モバイル プッシュ通知、SignalR によるリアルタイム通知 (自動スケール アウト)、お客様のコンシューマー アプリで利用できるソーシャル認証、一時的な接続シナリオでのオフライン データ同期などがあります。 企業向けシステムへの接続: アプリの利用者が Active Directory を使用してログインできる機能や、SharePoint や Office 365 などの企業資産にアクセスできる機能が利用できる点は、企業の開発者の方にとっては価値のあることでしょう。さらに、オンプレミス環境の資産へのシームレスな接続が実現されているので、インターネット上に公開されていないデータベースおよび Web サービスへのアクセスが可能です。 Visual Studio との統合: 普段使用している IDE に、Mobile Services 向けの専用のプロジェクト テンプレートおよびスキャフォールディングが含まれています。さらに、公開とリモート デバッグに関する最高レベルのサポートを提供しています。 クライアント SDK による、あらゆるモバイル プラットフォームで利用できるターンキー バックエンド 任意の環境で、容易に Mobile Services の利用を開始できます。いつものように Microsoft Azure 管理ポータルにアクセスし、Mobile Services を新たに作成します。ウィザードの最初の画面で、バックエンドに [.NET] を選択します。サービスを作成したら、[Quickstart] タブへと進み、対象とするクライアント プラットフォームのスターター プロジェクトをダウンロードします。 Visual Studio で利用を開始したい場合には、まずローカル プロジェクトを作成します。Mobile Services は、後でプロジェクトを公開するときに作成できます。ただし、この方法には Visual Studio 2013 Update 2 以降が必要です。 どちらの方法でも、Mobile Services .NET テンプレート プロジェクトを取得します。なおこれは、追加の NuGet パッケージがほとんど使用されていない Web API プロジェクトです。 TodoItemController.cs コントローラー ファイルを開いて内容を確認します。GetAllTodoitems() メソッド内にブレークポイントを設定します。このコントローラーは、Mobile Services .NET サポートを使用してデータを扱う方法を示しています。 public class TodoItemController : TableController<TodoItem> {     protected override void Initialize(HttpControllerContext controllerContext)     {         base.Initialize(controllerContext);         csharp_testContext context = new csharp_testContext();         DomainManager = new EntityDomainManager<TodoItem>(context, Request, Services);     }       // テーブルの取得/TodoItem     public IQueryable<TodoItem> GetAllTodoItems()     {         return Query();     }       // テーブルの取得/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959     public SingleResult<TodoItem> GetTodoItem(string id)     {         return Lookup(id);     }       // テーブルの修正/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959     public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)     {         return UpdateAsync(id, patch);     }       // テーブルの作成/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959     public async Task<IHttpActionResult> PostTodoItem(TodoItem item)     {         TodoItem current = await InsertAsync(item);         return CreatedAtRoute("Tables", new { id = current.Id }, current);     }       // テーブルの削除/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959     public Task DeleteTodoItem(string id)     {         return DeleteAsync(id);     } } ここで既に、TodoItem リソースで使用できるすべての主要な CRUD メソッドをスキャフォールディングしています。お気付きかと思いますが、このコントローラーは、既定で EntityDomainManager を使用しています。これは、Entity Framework モデルの上部にあるシン ラッパーです。代わりに次のデータ ストアを使用するように切り替えるのも簡単にできます。 MongoDB: WindowsAzure.MobileServices.Backend.Mongo (英語) NuGet パッケージから、MongoDomainManager を使用します。詳しくは、こちらのブログ記事 (英語) を参照してください。 Azure Table Storage: WindowsAzure.MobileServices.Backend.Storage (英語) NuGet パッケージから StorageDomainManager を使用します。詳細については、こちらのチュートリアル (英語) を参照してください。 Mobile Services .NET サポートを利用すると、Mobile Services バックエンドをローカルで実行して、バックエンド ロジックをデバッグできます。F5 キーをクリックして、既定のページで [try it out] を選択します。ご期待どおり、Mobile Services .NET サポートには、ご利用の Web API 用のヘルプ ページが含まれます。[GET tables/TodoItem] をクリックして、メソッド ドキュメントとテスト クライアントを呼び出します。[try this out] リンクをクリックし、次に [send] をクリックして GetAllTodoItems() メソッドを呼び出します。ご想像のとおり、先ほど設定したブレークポイントで停止します。 バックエンド API の開発が終わったら、Web API を Mobile Services に公開できます。公開のサポート機能が Visual Studio に組み込まれているので、操作はプロジェクトを右クリックして [Publish] を選択するだけです。既存の Mobile Services を選択するか、または Visual Studio で直接新規に作成できます。このとき Azure ポータルに移動する必要はありません。 既存の Web API ソリューションはいずれも Mobile Services に公開可能で、Web API の管理およびモニタリングをすばやく Azure に移行することができます。 Mobile Services .NET サポートの詳細については、次のチュートリアルを参照してください。 Mobile Services .NET の利用を開始する (英語) Mobile Services .NET でデータの利用を開始する (英語) Mobile Services .NET で認証の利用を開始する (英語) Mobile Services .NET でプッシュ通知の利用を開始する (英語) ご利用のモバイル API に適したトップ クラスのホスティング 経験のある Web API 開発者なら、API を Mobile Services に公開して、どんな付加価値が得られるのだろうかかと疑問に感じていらっしゃるかもしれません。何しろ、Web API を Azure とオンプレミスの両方でホストする簡単な方法はたくさんあります。では、Mobile Services により無料で利用できる、付加価値のある機能を見ていきましょう。次のようなものがあります。 監視と診断: Mobile Services では、インストルメンテーションと監視の機能に支えられた 99.9% の SLA を提供しています。これらの機能は、API の正常な実行を維持するために組み込まれているものです。マイクロソフトは、提供する有料のサービス レベルにおいて、サービスの HTTP トラフィックおよび SQL 接続を監視し、エラーの発生率が高くなり始めたらお客様にご連絡いたします。これは、エンドポイントの監視およびアラートを始めとする、さまざまな優れたセルフサービス型機能に加えて提供されています。 修正プログラムの自動適用: マイクロソフトは、毎週新しいコードをホスティング環境にデプロイしています。お客様がご利用のアプリをデプロイし直す必要はありません。修正される不具合が Mobile Services のランタイムに関するものなのか、Azure の依存関係に関するものなのか、または、新機能に関するものなのかに関わらず、お客様の Mobile Services に展開される変更は、サービスを中断することなく、透過的に行われます。もちろん、マイクロソフトは大幅な変更のデプロイは行いません。行われる変更はすべて、下位互換性が確保されています。 クラウド資産の自動プロビジョニング: お客様が Mobile Services を作成する際に、お客様のサービス用の SQL Database と通知ハブ (マイクロソフトのプッシュ通知エンジン) のプロビジョニングおよび構成をマイクロソフトが行い、すべての関連する接続文字列が構成済みであることを確認します。さらに、スケジュールされたジョブとハイブリッド接続 (オンプレミス接続の場合) の作成は、クラウド環境でほんの数クリックで簡単に行うことができます。Mobile Services は、ご利用のサービスに適切なすべての関連クラウド資産へ接続する、動作の速いゲートウェイを提供します。 高付加価値のモバイル バックエンド機能 Mobile Services を使用したアプリの開発を始めれば、数多くの必要な機能をすぐに利用できることに気付かれるでしょう。これにより、製品化に要する時間を大幅に短縮できます。次のような機能がすぐにご利用いただけます。 ターンキー型の認証: Mobile Services には、一般的なほとんどの認証シナリオで必要な、すべてのクラウド資産およびフレームワーク コードが含まれています。Microsoft アカウント、Facebook、Twitter、または Google を利用したソーシャル ログイン、および AAD を利用したエンタープライズ ログインを容易に有効化できます。フレームワークの構成に必要なものがすべて揃っているため OAuth の専門家になる必要がなく、構成設定をいくつか指定するだけで、後の作業は Mobile Services に任せておけます。詳しくは、こちらのチュートリアル (英語) を参照してください。 拡張性の高いプッシュ通知: Mobile Services は、クラウドでホストされたプッシュ エンジンを備えています。これにより、主要なデバイス プラットフォーム (Windows、iOS、Android、Kindle) すべてにわたる、大量の通知を送信できます。必要なのは、接続されている無数のデバイスへと通知を行う API を 1 つ呼び出すことだけです。また、タグ付けとタグ式がサポートされるているので、ユーザーを容易に区分できます。他にも、デバイス上で通知のカスタマイズを可能にするテンプレートもサポートされます。詳しい手順については、こちらのドキュメント (英語) を参照してください。 オフライン同期: 現在お客様から、ネットワーク接続が利用できないときでもモバイル アプリの動作を継続させたいという要望をいただいています。Mobile Services では、主要なクライアント プラットフォームすべてにわたって、組み込み型のオフライン SQLite ベースの同期をサポートしています。詳しくは、こちらのページ (英語) をご覧ください リアルタイム: プッシュ通知機能は、お客様のアプリに対する顧客エンゲージメントの強化に効果的ですが、お客様のアプリで拡張性に優れた、高帯域幅かつ低レイテンシの接続を提供するには、別のツール セットが必要です。Mobile Services では、WebSocket および SignalR に基づく、組み込み型のリアルタイム サポートを提供します。これにより、お客様のアプリとの双方向のメッセージングが可能になります。このサービスには、組み込み型のメッセージ バス (バックプレーン) が含まれており、お客様のアプリの拡張に伴い、シームレスにスケールアウトできます。また、お客様が利用するその他のサービスと同じ認証パイプラインとの統合により、ユーザーの認証および承認が容易です。詳しくは、こちらのブログ記事 (英語) を参照してください。 企業向けシステムへの接続 .NET は、企業で一般的な選択肢となるプラット フォームです。そのためマイクロソフトでは、.NET 言語をサポートすることで、ビジネス アプリケーションの開発者を支援できる数多くのシナリオを推進してきました。こちらのページでは、詳しい情報と動画を参照できます。 Active Directory ログインおよび代理アクセス機能: 企業向けシナリオでは、ドメイン ID を使用してアプリ ユーザーをログインできるようにすることは重要な要件です。これにより、アカウント ライフタイムの管理をシンプルに行え、また SharePoint Online や Office 365 などの Active Directory によって保護されているクラウド資産にユーザーがアクセスできるようになります。Active Directory 認証に対応するアプリの構成に関する詳細は、こちらのチュートリアル (英語) を参照してください。代理アクセスの構成方法については、こちらの動画 (英語) をご覧ください。 オンプレミス接続: データベースや Web サービスなどの一部の企業資産は、機密データが含まれているため、またはクラウドに移行できない他の理由のために、オンプレミスで保持する必要があります。それでも、「ハイブリッド接続」機能を通じて、これらの資産を Mobile Services で活用することは可能です。これにより、オンプレミスのトラフィックをクラウドに中継できます。こちらの動画による説明 (英語) およびチュートリアル (英語) を参照してください。 Xamarin SDK: Xamarin では、クライアント側のフレームワーク、および C# を使用してクロスプラットフォームのアプリ (Android、iOS など) を作成できるツールセットを提供します。他のプラットフォームで培ったスキルを応用できるので、マイクロソフト製品に慣れた開発者は効率的に開発を行えます。Mobile Services では、Xamarin ベースのアプリ構築に役立つ SDK と優れたリソース (英語) を利用できます。 アクセラレータ: 利用を開始する際に良い参考となる実装例がある場合は、シナリオの実装を検討するのが最も簡単な方法です。チームは最近、一連の「アクセラレータ」の構築に注力してきました。これは、一般的なユーザーの業界のニーズを満たし、Mobile Services を使用した対処方法を示す、洗練されたアプリです。これらのアプリは Windows ストアで公開され、ソース コードを使用または変更することができます。詳細については、こちらのページ (英語) を参照してください。現在のところ、2 つのアクセラレータ (フィールド エンジニアおよび販売員のシナリオ) が利用可能ですが、他のものも間もなく公開される予定です。 Visual Studio との統合 Visual Studio には、上記の機能の他にも Mobile Services の開発およびデバッグに使用できる便利なツールが含まれています。スキャフォールディング機能が利用可能になったので、これを使用してテーブル コントローラー (関連データの格納用)、ユーザー定義コントローラー (任意の HTTP API の構築用)、およびスケジュールされたジョブを作成できます。 また、リモート デバッグがサポートされており、デバッグについても快適なエクスペリエンスを利用できます。操作は、サーバー エクスプローラーで該当の Mobile Services を右クリックし、[Attach Debugger] を選択するだけです。この機能を最大限に活用するために、ぜひお客様のサービス コードのデバッグ ビルドを公開してください。 サーバー エクスプローラーのもう 1 つの優れた機能は「View Logs」コマンドです。これを使用すると、クラウド上の Mobile Services から出力された、エラー メッセージやスタック トレースなどのログを閲覧できます。 マイクロソフトは、この新しい機能群がきっかけとなり、お客様の次のプロジェクトで、Mobile Services をお試しいただけることを願っております。ご不明な点やフィードバックがある場合は、どうぞお気軽に Twitter アカウント @theYavor までお寄せください。

Posted by on 28 July 2014 | 1:30 am