Något vi har kunnat göra länge är att rendera partiella vyer med ASP.NET MVC är att använda Html.RenderPartial(). Det gör det möjligt att ange namnet på en vy, samt skicka in en eventuell modell som skall användas för den partiella vyn.

I ASP.NET MVC så får vi två nya metoder som går ett steg längre och ger oss mer kontroll över vad som sker innan den partiella vyn renderas. De två metoderna som har tillkommit är Html.Action() och Html.RenderAction().

Det som sker när vi använder dessa metoder är att vi istället för att anropa en user control direkt, går igenom en Action-metod.

För att testa funktionaliteten så behöver vi först en modell kallad Customer.

namespace Mvc2Beta.Models
{
    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

Sedan så behöver vi en partiell vy som visar ett eventuellt inskickat namn. Den skall vara hårt typad mot Customer-klassen.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Mvc2Beta.Models.Customer>" %>
Hej, <%= Model.Name %>!

Nu har vi det som krävs för att vi ska kunna anropa den partiella vyn. Nästa steg blir att implementera de olika metoder som kan användas för att anropa den.

De tre sätt som vi ska hämta in vyn på är genom Html.RenderPartial(), Html.Action() och Html.RenderAction().

Vi börjar med att lägga in det som behövs i vyn där de skall visas:

<ul>
    <li>
        RenderPartial: <% Html.RenderPartial("Name", new Mvc2Beta.Models.Customer() {Id = 1, Name = "Mikael"}); %>
    </li>
    <li>
        RenderAction: <% Html.RenderAction("Name", new Mvc2Beta.Models.Customer() { Id = 1, Name = "Mikael" }); %>
    </li>
    <li>
        Action: <%= Html.Action("Name", new Mvc2Beta.Models.Customer() { Id = 1, Name = "Mikael" }) %>
    </li>
</ul>

Vi kan se att RenderAction fungerar på samma sätt som RenderPartial i vyn. Action returnerar däremot en sträng som vi antingen kan skriva ut direkt, eller som vi kan använda på annat sätt.

Då Action och RenderAction inte går direkt mot den partiella vyn, utan mot en Action-metod så kommer vi att få ett fel om vi kör koden nu. Det vi behöver göra är att skapa en metod vid namn ”Name” och som tar emot ett Customer-objekt som vi vill vidarebefordra till vår partiella vy.

Vi lägger det här i controller-klassen:

public ActionResult Name(Customer customer)
{
    return PartialView(customer);
}

Vi behöver inte ta emot ett Customer-objekt som parameter i metoden, men jag gör det nu för att det ska bli enklare att jämföra de olika varianterna. Däremot så måste vi returnera en PartialView med ett Customer-objekt.

Om vi nu kör sidan så kan vi se att alla tre metoder returnerar samma vy med samma information. Skillnaden ligger i hur vi anropar den.

Det finns nu alltså tre olika metoder för tre olika scenarion.

Vill du snabbt och enkelt rendera en partiell vy med eller utan en modell?

- Använd Html.RenderPartial().

Vill du rendera en partiell vy, men kunna påverka flödet i en Action-metod?

- Använd Html.RenderAction().

Vill du ta emot en partiell vy i en sträng efter att ha haft möjligheten att påverka flödet i en Action-metod?

- Använd Html.Action().

Det finns ingen metod för alla scenarion, utan det gäller att välja den som passar bäst för det enskilda scenariot.

I ASP.NET MVC 2 Beta så kommer det funktionalitet i Visual Studio för att kunna skapa areor enklare. Tidigare så har det krävt en del jobb och manuellt pill i konfig-filer, men nu finns allt inbyggt.

När vi skapar ett nytt ASP.NET MVC 2 Beta-projekt och högerklickar på projektet i Solution Explorer så ser vi det här:

1 - New

När vi klickar på ”Area…” så får vi upp en ruta där vi får skriva in ett namn på arean. Jag skriver in ”NewArea” och klickar på ok.

Det som sker nu är att det skapas en ny area med det namnet vi angav, med allt som behövs för att vi skall kunna använda den.

Kikar vi i global.asax så kan vi se att arean registreras:

AreaRegistration.RegisterAllAreas();

Ser vi i den nyskapade Areas-mappen så kan vi se att vi har en AreaRegistration-klass, vilken vi använder för alla routes som ska finnas för arean.

I Solution Explorer har vi det här:

clip_image004

Utan att skriva en rad kod så har vi fått en area i projektet.

Det går tyvärr inte att skapa nya projekt för areor på det här sättet, utan det går bara att lägga till nya areor i det befintliga projektet.

Microsoft släppte ikväll ASP.NET MVC 2 Beta. Det går inte att använda det tillsammans med Visual Studio 2010 Beta 2, utan det måste användas med Visual Studio 2008.

Ladda ned det här:

http://www.microsoft.com/downloads/details.aspx?FamilyID=4817cdb2-88ea-4af4-a455-f06b4c90fd2c&displaylang=en

I .NET 4.0 så ingår webbkontroller för att skapa diagram (så kallade ”charts”) med bland annat ASP.NET. Då det är vanliga webbkontroller så innebär det att de är anpassade för web forms, men de går faktiskt utmärkt att använda för ASP.NET MVC.

Innan vi lägger till diagrammen så börjar vi med att skapa ett ASP.NET MVC-projekt med en ny modell kallad Article. Den har två properties, Name och Category.

Utseendet på den klassen ser ut så här:

namespace MvcChart.Models
{
    public class Article
    {
        public string Name { get; set; }
        public string Category { get; set; }
    }
}

Vi skapar även en ny ActionResult-metod i HomeController som fyller denna med dummy-data, samt skapar en vy för denna som listar upp datan.

public ActionResult Articles()
{
    List<Article> articles = new List<Article>()
    {
        new Article() { Name = "Artikel 1", Category = "Äpplen" },
        new Article() { Name = "Artikel 2", Category = "Äpplen" },
        new Article() { Name = "Artikel 3", Category = "Äpplen" },
        new Article() { Name = "Artikel 4", Category = "Päron" },
        new Article() { Name = "Artikel 5", Category = "Päron" },
        new Article() { Name = "Artikel 6", Category = "Bananer" }
    };
 
    return View(articles);
}

Om vi kikar på /Home/Articles så får vi nu upp en tabell med namnen på artiklarna samt vilken kategori de tillhör. Vi kan dock ej på ett enkelt sätt se hur många artiklar det finns i varje kategori, så där kan vi ha ett diagram som gör det åt oss.

Diagrammet kommer att finnas under en ny controller kallad ChartController. Här har vi en metod kallad Articles(). I denna controllern skapar vi ett diagram som returneras direkt till vyn som en png-bild.

Chart-funktionaliteten som vi vill åt ligger under System.Web.UI.DataVisualization.Charting, vilket i sin tur ligger i System.Web.DataVisualization.dll. Vi måste skapa en referens till den dll:en i Visual Studio då den inte ingår som standard i projekten. Den finns dock med bland listan med assemblies i GAC:n.

Den fullständiga koden för att returnera diagrammet med samma dummy-data som vi hade i den andra controllern ser ut så här:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.UI.DataVisualization.Charting;
using MvcChart.Models;
 
namespace MvcChart.Controllers
{
    public class ChartController : Controller
    {
        public ActionResult Articles()
        {
            //Skapa några artiklar
            List<Article> articles = new List<Article>()
            {
                new Article() { Name = "Artikel 1", Category = "Äpplen" },
                new Article() { Name = "Artikel 2", Category = "Äpplen" },
                new Article() { Name = "Artikel 3", Category = "Äpplen" },
                new Article() { Name = "Artikel 4", Category = "Päron" },
                new Article() { Name = "Artikel 5", Category = "Päron" },
                new Article() { Name = "Artikel 6", Category = "Bananer" }
            };
 
            //Skapa en chart
            Chart chart = new Chart()
            {
                Height = 300,
                Width = 300,
                ImageType = ChartImageType.Png
            };
 
            //Visa som 3D
            ChartArea chartArea = chart.ChartAreas.Add("Categories");
            chartArea.Area3DStyle.Enable3D = true;
 
            //Skapa en serie med grupperna
            Series categories = chart.Series.Add("Categories");
            categories.ChartType = SeriesChartType.Doughnut;
 
            //Gruppera per CategoryId
            IEnumerable<IGrouping<string, Article>> catgroup = articles.GroupBy(a => a.Category);
 
            //Lägg till en ny DataPoint för varje kategori
            foreach (IGrouping<string, Article> item in catgroup)
            {
                categories.Points.Add(new DataPoint()
                {
                    Label = String.Format("{0} ({1})", item.Key, item.Count()),
                    YValues = new Double[] { item.Count() }
                });
            }
 
            //Spara ned bilden i en memorystream
            MemoryStream ms = new MemoryStream();
            chart.SaveImage(ms);
 
            //Returnera bilden direkt till vyn
            return File(ms.GetBuffer(), "image/png");
        }
    }
}

Det första som händer här är att dummydatan skapas upp och läggs i en lista. Sedan skapar vi en instans av Chart, vilket är klassen som används för de olika typerna av diagram. Vi anger även storlek på denna och säger att det ska bli en png-bild.

Nästa steg blir att skapa en ChartArea så att vi kan sätta inställningar för diagrammet. Det enda vi gör här är att sätta det som 3D för att det skall bli snyggare. Det finns även många andra inställningar man kan göra.

Efter det så skapar vi en serie. En serie är en samling data som skall visas upp på ett diagram. Man kan ha flera serier på samma diagram, vilka då visas på samma bild. Just den här serien skall vara av typen ”Doughnut”.

Sedan så grupperar vi alla artiklar efter kategori och lägger till en DataPoint för var och ett. En DataPoint är ett enskilt värde i diagrammet. Vi sätter även en Label på dessa för att kunna se vilken kategori det gäller, samt hur många artiklar det finns för den.

Det sista som händer är att vi sparar ned diagrammet i en memorystream som sedan returneras direkt till sidan som en png-bild.

Om vi surfar direkt till /Chart/Articles nu så får vi upp den här bilden:

Articles-1

Vi kan enkelt se att t.ex. hälften av alla artiklar (tre stycken) ligger i kategorin ”Äpplen”.

De går även att använda andra typer av diagram, så genom att byta ut Doughnut mot Pyramid så kan vi få det här:

Articles-2

Och väljer vi Bar så får vi det här:

Articles-3

Det finns väldigt många olika typer av diagram samt många olika sätt att påverka utseendet på, så för en bra genomgång av detta så rekommenderar jag en titt på exempelsidan som man kan ladda ned här:

http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=1591

Samt dokumentationen som finns här:

http://www.microsoft.com/downloads/details.aspx?FamilyId=EE8F6F35-B087-4324-9DBA-6DD5E844FD9F&displaylang=en

Då grafen är en vanlig vy så fungerar routing för den precis som för allt annat. Vi kan gå tillbaka till Articles-vyn som vi skapade för HomeControllern och lägga till det här:

<img src="<%=Url.Action("Articles", "Chart") %>" alt="Diagram över artiklar" />

Om vi nu går in på /Home/Articles så ser sidan ut så här:

Articles-4

För att bygga vidare på den här funktionaliteten så skulle man t.ex. kunna göra det möjligt att skicka in variabler till sina ActionResult-metoder i ChartController och därmed göra diagrammen ännu mer dynamiska.

Är du sugen på att vinna ett eget exemplar av Microsoft Arc Mouse?

Det enda du behöver göra för det är att skriva en artikel, en applikation eller spela in en video som handlar om Visual Studio 2010 eller .NET 4.0. Personerna bakom de bästa bidragen belönas med en varsin Arc Mouse!

Tävlingen håller på fram till 22 november och man kan lämna in så många bidrag man vill.

De bästa bidragen kommer även att publiceras på svenska MSDN:s sida för Visual Studio 2010 och .NET 4.0:

http://www.msdn.se/vs2010

För att komma till tävlingen så klicka på länken nedan:

http://www.aspsidan.se

Lycka till!

Precis som rubriken säger så kan man använda HtmlEncode() utan att använda HtmlEncode(), hur logiskt som helst!

I ASP.NET 4.0 så kommer ett nytt kodblock, vilket låter oss göra just det här. Något som man väldigt ofta gör på sina sidor är att skydda sig mot HTML genom att använda HtmlEncode() runt strängen som skall skrivas ut för att bl.a. < skall bli &lt; och > skall bli &gt;. Det nya kodblocket i ASP.NET 4.0 låter oss skippa det här och gör det mycket smidigare att säkra upp sidan mot HTML.

Som exempel så har jag skapat upp ett ASP.NET MVC-projekt i Visual Studio 2010 Beta 2. Jag har inte förändrat något, utan allt är precis som det är från start.

I Index-metoden i HomeController.cs så har vi den gamla vanliga raden:

ViewData["Message"] = "Welcome to ASP.NET MVC!";

Den ser till att ett meddelande skickas till vyn. Väl i vyn så skrivs det ut med HtmlEncode för att se till att inte eventuell HTML skrivs ut:

<h2><%= Html.Encode(ViewData["Message"]) %></h2>

Det vi ska göra nu är att skicka med HTML för att se så att det fungerar som väntat.

Vi skriver om C#-koden tidigare så texten blir kursiv:

ViewData["Message"] = "<i>Welcome to ASP.NET MVC!</i>";

När vi nu ser på sidan så ser vi att texten skrivs ut precis som strängen ser ut, dvs i rent text utan att vara kursiv.

Om vi nu plockar bort Html.Encode() från aspx-filen så blir dock texten kursiv.

Med hjälp av det nya kodblocket så kan vi utan att lägga tillbaka Server.HtmlEncode() ta nytta av funktionen.

Genom att byta ut = mot : i kodblocket så körs HtmlEncode automatiskt på strängen och skriver ut den.

<h2><%: ViewData["Message"] %></h2>

Det är ett mycket renare sätt att lösa det på, då det väldigt ofta händer att man vill köra HtmlEncode.

Det här är en ny funktion i ASP.NET 4.0 och går ej att använda med någon av de tidigare versionerna.

Microsoft släppte för någon timme sedan Visual Studio 2010 Beta 2. Jag hade läst att det skulle komma under dagen så jag satt och slet ut F5-knappen idag. :-)

De olika versioner av Visual Studio 2010 Beta 2 som finns är:

  • Visual Studio 2010 Ultimate Beta 2
  • Visual Studio 2010 Professional Beta 2
  • Visual Studio 2010 Premium Beta 2
  • Visual Studio 2010 Express Combo Beta 2
  • Visual Studio 2010 VWD Express Beta 2
  • Visual Studio 2010 VCS Express Beta 2
  • Visual Studio 2010 VC Express Beta 2
  • Visual Studio 2010 VB Express Beta 2

De tre fetmarkerade är de tre olika versioner av Visual Studio som finns, de övriga är Express-versionerna. Vi kan se några intressanta saker här. Dels så finns det nya namn för Visual Studio – Ultimate, Professional och Premium, dvs precis som för Windows. Sen så har vi även Express Combo som ser ut att vara ett paket med alla Express-versioner.

Jag påbörjade nedladdningen av VS 2010 Ultimate på jobbet, men var tvungen att gå hem, så jag får nog vänta ett tag innan jag får leka ordentligt. :-(

Ni kan dock se fram emot ett antal bloggposter dels här, men även på http://www.msdn.se/vs2010 som är svenska Microsofts sida för Visual Studio 2010 och .NET 4.0.

För information om vad som är nytt i ASP.NET 4.0 Beta 2 så kan ni hitta information här:

http://www.asp.net/learn/whitepapers/aspnet40/

Till nästa gång så koda lugnt! Eller vad tusan.. Koda så det ryker! :-)

Något som är riktigt häftigt är Microsoft Tags. Det är små taggar i form av bilder som man kan använda för att t.ex. göra det enkelt att surfa till en viss URL genom att bara peka mobilkameran mot den. Det kan användas i reklamsyfte, man kan ha det på sitt visitkort för att länka till bloggen eller vad man nu önskar.

Det är svårt att inse hur häftigt det verkligen är förrän man testar det själv!

För att kunna testa det här så surfa med mobiltelefonen till:

http://gettag.mobi/

Det fungerar på de flesta mobiltelefoner, så jag kan rekommendera att ni laddar ned det på direkten. När man startar programmet på mobilen så aktiveras kameran, och när man riktar den mot en bild så startar webbläsaren upp och går till URL:en som bilden är riktad mot.

För att kunna testa att det fungerar så kan ni testa att köra programmet på mobiltelefonen och rikta kameran mot bilden nedan:

1 - blog

Ni bör nu komma till min blogg på mobiltelefonen!

För att kunna skapa taggar som denna själv så kan ni skapa ett konto här:

http://tag.microsoft.com

Det gör det möjligt att skapa upp egna taggar på sidan och generera upp dem i olika färger och typer.

För att kunna ta del av det som finns i artikeln så bör ni även registrera er för API:t, vilket ni kan göra här:

http://www.microsoft.com/tag/content/support/developer/

Ni bör efter ett tag få en API-nyckel skickad till mailen. Den behövs för att ni skall kunna generera taggarna själva.

Skapa egna funktioner för att generera taggar

För att vi ska kunna generera taggarna så har jag en solution i Visual Studio med två klasser, ett klassbibliotek samt ett ASP.NET MVC 2-projekt.

I klassbiblioteket så behöver vi en service-referens till den här URL:en:

https://ws.tag.microsoft.com/MIBPService.wsdl

Vi kommer även att ha en klass vid namn TagRepository där vi lägger till metoderna för att hantera alla taggar.

I den här klassen har vi metoder för att skapa kategorier, skapa taggar och sedan hämta dem.

using MicrosoftTag.TagService;
 
namespace MicrosoftTag
{
    public class TagRepository
    {
        private const string AccessToken = "DIN PRIVATA API-NYCKEL";
 
        UserCredential _credentials;
 
        public TagRepository()
        {
            _credentials = new UserCredential();
            _credentials.AccessToken = AccessToken;
        }
 
        public void CreateTag(string categoryname, URITag tag)
        {
            using (MIBPContractClient client = new MIBPContractClient())
            {
                client.CreateTag(_credentials, categoryname, tag);
            }
        }
 
        public void CreateCategory(Category category)
        {
            using (MIBPContractClient client = new MIBPContractClient())
            {
                client.CreateCategory(_credentials, category);
            }
 
        }
 
        public byte[] GetBarcode(string categoryname, string tagname)
        {
            using (MIBPContractClient client = new MIBPContractClient())
            {
                return client.GetBarcode(
                    _credentials,
                    categoryname,
                    tagname,
                    ImageTypes.gif,
                    0.75F,
                    DecorationType.HCCBRP_DECORATION_NONE,
                    false
                    );
            }
        }
    }
}

Jag kommer inte att gå in så djupgående vad alla anrop gör, utan det är ganska självförklarande. Det som vi eventuellt skulle kunna påverka här är GetBarcode där vi har möjlighet att påverka de taggar som hämtas ut från tjänsten. Vi kan t.ex. välja att ha ett annorlunda utseende på taggen, vi kan välja att ha den i svartvitt, vi kan ändra storlek (0.75-2 inches) m.m. Här har vi den minsta taggen samt har satt att vi inte vill ha någon dekoration runt. Det ger bilden som jag visade tidigare.

Nästa steg blir att skapa ASP.NET MVC 2-projektet. Det här projektet skall ha en referens till klassbiblioteket. Vi måste även kopiera några rader från app.config i klassbiblioteket till web.config i webbprojektet för att webbtjänsten skall hittas.

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IMIBPContract" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </basicHttpBinding>
        <customBinding>
            <binding name="BasicHttpBinding_IMIBPContract1">
                <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
                    messageVersion="Soap11" writeEncoding="utf-8">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                </textMessageEncoding>
                <httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
                    maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
                    bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
                    realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                    useDefaultWebProxy="true" requireClientCertificate="false" />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="https://ws.tag.microsoft.com/Service.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMIBPContract"
            contract="TagService.IMIBPContract" name="BasicHttpBinding_IMIBPContract" />
    </client>
</system.serviceModel>

För att slippa problem med storleken på bilden som hämtas så kommer vi även att behöva ändra värdet på maxArrayLength under basicHttpBinding\binding\readerQuotas till 16384000. Annars kommer ett lustigt felmeddelande som säger att gränsen har överskridits.

Nästa steg blir att skapa en controller vid namn TagController. Här har vi våra metoder för att kunna skapa kategorier och taggar, samt för att kunna hämta taggarna.

using System.Web.Mvc;
using MicrosoftTag;
using MicrosoftTag.TagService;
 
namespace Web.Controllers
{
    public class TagController : Controller
    {
        TagRepository repository = new TagRepository();
 
        public ActionResult Index()
        {
            return View();
        }
 
        public ActionResult CreateTag()
        {
            return View();
        }
 
        [HttpPost]
        public ActionResult CreateTag(string category, FormCollection collection)
        {
            URITag tag = new URITag();
 
            UpdateModel(tag);
 
            repository.CreateTag(category, tag);
 
            try
            {
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
 
        public ActionResult CreateCategory()
        {
            return View();
        }
 
        [HttpPost]
        public ActionResult CreateCategory(FormCollection collection)
        {
            Category category = new Category();
 
            UpdateModel(category);
 
            try
            {
                repository.CreateCategory(category);
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
 
        public ActionResult GetBarcode()
        {
            return View();
        }
 
        [HttpPost]
        public ActionResult GetBarcode(string category, string tag)
        {
            try
            {
                return File(repository.GetBarcode(category, tag), "image/gif");
            }
            catch
            {
                return View();
            }
        }
    }
}

Våra två formulär har en varsin metod för att ta emot datan och posta till tjänsten. Där kommer sedan kategorier och taggar att lagras. Sedan har vi en metod för att posta namn på kategorin och namnet på taggen för att utifrån det kunna hämta taggarna. Det finns för närvarande ingen metod för att hämta en lista på alla kategorier och taggar, men förhoppningsvis så kommer det i en senare version. Men nu får vi alltså sköta det själva.

Index-sidan kommer att vara en enkel sida som länkar till de olika vyerna för taggar.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Administration av tags</h2>
    <p>Använd den här sidan för att administrera dina tags.</p>
    <ul>
        <li><%= Html.ActionLink("Skapa tag", "CreateTag", "Tag") %></li>
        <li><%= Html.ActionLink("Skapa kategori", "CreateCategory", "Tag") %></li>
        <li><%= Html.ActionLink("Hämta tag", "GetBarcode", "Tag") %></li>
    </ul>
</asp:Content>

Sedan kommer vi att behöva ha sidor för de olika formulären. För kategorivyn och taggvyn så genererar vi bara standardsidor för Create som vi binder mot Category och URITag i webbtjänsten. Det hade varit snyggare att ha egna klasser att binda mot, men då det här fungerar snabbt och enkelt så kör vi på det nu.

Om vi nu testar att skapa en kategori så kommer vi att se att den kategorin dyker upp på officiella administrationssidan för Microsoft Tags. Detsamma gäller om vi skapar upp taggar. Vi kan nu alltså enkelt skapa upp taggar som sedan kan användas för att vidarebefordra personer till olika sidor.

Det intressanta sker nu när vi skall skapa sidan för att hämta taggar. Vi börjar med att skapa vyn för formuläret. Det skall inte vara kopplat till någon modell.

Sidan i sin helhet ser ut så här:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>GetBarcode</h2>
    <%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
    <% using (Html.BeginForm()) {%>
        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="category">Kategori:</label>
                <%= Html.TextBox("category") %>
                <%= Html.ValidationMessage("category", "*")%>
            </p>
            <p>
                <label for="tag">Namn på tag:</label>
                <%= Html.TextBox("tag") %>
                <%= Html.ValidationMessage("tag", "*") %>
            </p>
            <p>
                <input type="submit" value="Hämta" />
            </p>
        </fieldset>
    <% } %>
    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>
</asp:Content>

För att testa det så börjar vi med att skapa en kategori vid namn ”Test” och sedan en tagg under den kategorin vid namn ”MSDN” och en URL som pekar mot http://www.msdn.se. När vi väljer att hämta en tagg och fyller i dessa uppgifter så får vi nu:

2 - msdn

Testa gärna att ändra koden så att ni kan få andra utseenden på taggarna. Jag bifogar projektet så att ni enkelt kan få ned det och börja labba själva (ni behöver dock ange en egen API-nyckel):

http://misc.mikaelsoderstrom.se/examples/MicrosoftTag.zip

Kom gärna med egna idéer över hur man kan använda dessa, eller exempel på där de används!

Scott Guthrie gick tidigare idag ut med att Microsoft Ajax Library Preview 6 har släppts. I samband med det så släpptes även Microsoft Ajax Minifier, vilket jag kommer att ta upp nu.

Med Microsoft Ajax Minifier så kan man krympa storleken på sin JavaScript-kod otroligt mycket. Det gör att koden kan laddas in snabbare på sidan och därmed ge en bättre användarupplevelse.

För att komprimera sina js-filer så finns det tre olika sätt, antingen använder man ajaxmin.exe som är ett program som kan anropas genom kommandoprompten, eller så använder man ajaxmintask.dll som kan användas med MSBuild för att komprimera dem vid kompilering, eller ajaxmin.dll som innehåller API:er som kan anropas från vanlig .NET-kod.

Både Microsoft Ajax Library Preview 6 och Microsoft Ajax Minifier går att ladda ned här:

http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34488

Tyvärr så saknas både ajaxmintask.dll och ajaxmin.dll i nedladdningen ovan i skrivande stund, men det hindrar oss inte från att köra den ändå. :-)

För att kunna anropa från en ASP.NET MVC-applikation så behöver vi först skapa upp en sådan. Vi skapar sedan en CompressControler och en vy för visning av dels formuläret och dels JavaScriptet som är komprimerat.

Sedan gör vi ett litet fulhack då dll:en inte finns, vi skapar en referens till ajaxmin.exe istället då den innehåller alla API:er som vi behöver.

Jag har även skapat en enkel model som kommer att användas i exemplet.

namespace JsCompress.Models
{
    public class JavaScript
    {
        public string OriginalJavaScript { get; set; }
        public string CompressedJavaScript { get; set; }
    }
}

Den innehåller originalversionen av JavaScriptet och den komprimerade versionen. Jag kommer inte att göra något med dessa förutom att skriva ut den komprimerade, men det skulle t.ex. kunna cachas för att snabbt kunna komprimeras på servern och laddas in på sidan.

Den fullständiga controllern ser ut så här:

using System.Web.Mvc;
using JsCompress.Models;
using Microsoft.Ajax.Utilities;
 
namespace JsCompress.Controllers
{
    public class CompressController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        public ContentResult Index(FormCollection collection)
        {
            JavaScript js = new JavaScript();
 
            UpdateModel(js);
 
            JSParser parser = new JSParser(js.OriginalJavaScript, null);
            Block block = parser.Parse(new CodeSettings());
            js.CompressedJavaScript = block.ToCode();
 
            return Content(js.CompressedJavaScript, "text/plain");
        }
    }
}

Det jag gör vid postning är att skapa en ny instans av JSParser, vilket kommer från exe-filen. Där skickar jag med originalversionen av JavaScriptet, vilket kommer med i postningen. Sedan parseas JavaScriptet och sparas i CompressedJavaScript.

Det sista som sker är att det skrivs ut på sidan som text/plain genom en ContentResult.

Det finns många inställningar för hur parsningen skall ske, så jag rekommenderar att ni läser igenom dokumentationen vilken följer med i nedladdningen.

Index-vyn i CompressController har bara ett enkelt fält:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<JsCompress.Models.JavaScript>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Komprimera JavaScript</h2>
    <% using (Html.BeginForm()) {%>
        <fieldset>
            <legend>Komprimera ett JavaScript</legend>
            <p>
                <label for="OriginalJavaScript">JavaScript:</label>
                <%= Html.TextArea("OriginalJavaScript", new { cols = "120", rows = "20" })%>
            </p>
            <p>
                <input type="submit" value="Compress" />
            </p>
        </fieldset>
    <% } %>
</asp:Content>

För att testa hur det fungerar så kommer jag att använda ett JavaScript som ser ut så här:

//En funktion som räknar ut x + y
function Sum(x, y) {
    return x + y;
}
 
alert(Sum(1, 2));

Om vi testar att stoppa in den i textrutan och väljer att komprimera så får vi nu upp det här:

function Sum(x,y){return x+y}alert(Sum(1,2))

Alla onödiga mellanslag och kommentarer har plockats bort, vilket gör att scriptet nu tar mindre plats.

Det kan antingen användas innan produktionssättning och sedan laddas upp, eller så kan ni modifiera det så att den genererar en kompilerad version direkt på servern varje gång filen uppdateras.

Projektet med exemplen finns att ladda ned här:

http://misc.mikaelsoderstrom.se/examples/jscompress.zip

Något som är väldigt vanligt på webbsidor (speciellt i CMS) är att man vill ha en Wysiwyg-editor på sidan för att enkelt kunna redigera sidorna och låta redaktörerna anpassa utseendet på texten samt lägga in bilder och annat.

När man vill lägga in en sådan så kan man ladda ned den och lägga in den på de ställen där det passar. Det kan dock krävas en del jobb, samtidigt som man kan behöva lägga in den på flera ställen. Dessutom så finns det en risk för att det kan bli onödigt mycket jobb för att vara säker på att den fortfarande fungerar om den byts ut.

Så hur kan man lösa det här på ett enkelt sätt?

UIHint används som bekant av både ASP.NET Dynamic Data och ASP.NET MVC 2 för att anpassa hur olika egenskaper skrivs ut på sidan. Man kan genom att ändra i en user control enkelt byta ut kontroller och vara säker på att de fortfarande fungerar. Jag kommer att gå igenom hur vi kan använda detta för att enkelt få till en Wysiwyg-editor istället för vanliga text-fält.

Först och främst så skall vi använda oss utav en modell kallad ”Customer” (surprise!). Den kommer att ha två egenskaper, ett id för att identifiera den aktuella kunden och sedan ”Information”, vilket kommer att vara en sträng med HTML där vi har information om kunden.

namespace Wysiwyg.Models
{
    public partial class Customer
    {
        public int Id { get; set; }
        public string Information { get; set; }
    }
}

Vi kommer även att ha en CustomerController. Vid skapandet väljer vi att få med de extra metoderna för att skapa, editera och ta bort. Vi har även med en metod här som används för att fylla på med lite dummy-data.

public List<Customer> GetCustomers()
{
    return new List<Customer>() {
        new Customer() {
            Id = 1,
            Information = "Hej 1"
        },
        new Customer() {
            Id = 2,
            Information = "Hej 2"
        },
        new Customer() {
            Id = 3,
            Information = "Hej 3"
        }
    };
}

Om vi nu skapar upp en Index-sida och en Edit-sida som vi fyller med informationen från GetCustomers() så kommer vi att kunna se informationen om dem och få möjligheten att få upp ett redigeringsformulär.

Formuläret ser dock rätt tråkigt ut i dess standardutförande:

1 - Form

Det vi vill ha istället för en enkel textruta är en Wysiwyg-editor där man skall kunna använda HTML för att snygga till texten.

Vi börjar med att skapa upp en EditorTemplate för det. Det gör vi genom att skapa upp en ASP.NET MVC User Control vid namn Wysiwyg.ascx och som vi lägger i Views\Shared\EditorTemplates. Vill vi ha en template för vanlig visning så lägger vi istället våra user controls i en mapp kallad DisplayTemplates.

Den nyskapade filen kommer att ha det här innehållet:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<%= Html.TextArea("Information", Model }) %>

Vi behöver även lägga till ett attribut på Information-fältet i en metadata-klass. Skapa upp en ny partiell klass till Customer som ser ut i stil med det här:

using System.ComponentModel.DataAnnotations;
 
namespace Wysiwyg.Models
{
    [MetadataType(typeof(Customer_Metadata))]
    public partial class Customer
    {
        class Customer_Metadata
        {
            [UIHint("Wysiwyg")]
            public string Information { get; set; }
        }
    }
}

Går vi in på sidan nu så kommer vi istället att ha en text-area, vilket är en bra början. Vi kan nu lägga till text på flera rader, men vi har fortfarande inget Wysiwyg-läge, så hur får vi dit det?

Först och främst så laddar vi ned CKEditor 3.0 (det hette tidigare FCKEditor, men bytte namn då det är alldeles för likt ett ord som också innehåller bokstäverna FCK ;-)). Det hittar vi här:

http://ckeditor.com

När det är nedladdat så lägger vi ckeditor-mappen i roten för får webbapplikation.

Nu behöver vi ändra lite i vår EditorTemplate för att få fram CKEditor istället för vår TextArea. Jag kommer att använda exempel-filerna som finns med i CKEditor, men ni kan lika gärna skapa egna för att kunna anpassa utseendet mer. För mer information om vad som går att göra så rekommenderar jag att ni kollar igenom exemplen som följer med, samt kollar igenom dokumentationen som finns på CKEditors hemsida.

Den modifierade versionen av Wysiwyg.ascx ser ut så här:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<script src="/ckeditor/ckeditor.js" type="text/javascript"></script>
<script src="/ckeditor/_samples/sample.js" type="text/javascript"></script>
<link href="/ckeditor/_samples/sample.css" rel="stylesheet" type="text/css" />
<%= Html.TextArea("Information", Model, new { @class = "ckeditor" }) %>

Jag har två referenser till js-filer och en till en css-fil här. Jag har även satt klassen för textarean till ”ckeditor”.

Om vi nu kollar på sidan igen så kommer vi att se en stor förändring:

2 - Wysiwyg

Genom att sätta [UIHint(”Wysiwyg”)] på valfritt fält i någon klass så kan vi alltså få in en Wysiwyg-editor direkt på sidan utan något strul alls.

Om vi postar formuläret nu så kommer vi dock att få ett felmeddelande på grund av ValidateRequest i ASP.NET. För att slippa detta så måste vi sätta ValidateInput till false på de controllers som man skall kunna posta HTML till. Det här är för att vara säker på att ingen postar HTML där det inte är meningen att man ska kunna göra det.

[AcceptVerbs(HttpVerbs.Post)]
[ValidateInput(false)]
public ActionResult Edit(int id, FormCollection collection)

När det här är gjort så kommer vi att kunna använda vår Wysiwyg-editor som om det vore vilken kontroll som helst på sidan.

Vem har sagt att programmering är svårt? :-)

Exemplet i artikeln finns att ladda ned här:

http://misc.mikaelsoderstrom.se/examples/wysiwyg.zip

More Posts Next page »