Skapa en gästbok med Linq 2 XML

by Reager 11. July 2009 20:26

I detta inlägg så ska vi skapa en gästbok där vi lagrar inläggen i ett XML-ark. Fördelen med XML-ark är att det inte krävs någon databas och är således väldigt lätt att installera, dock har det även sina nackdelar men de ska vi inte ta upp här.

Börja med att skapa en ny webbplats i Visual Studio. I mappen App_Data skapar du en xml-fil som heter posts.xml. I denna fil skapar du sedan ett rootelement vid namn posts så filen ser ut så här

<?xml version="1.0" encoding="utf-8"?>
<posts></posts>

När detta är klart ska vi skapa en klass som skall representera våra inlägg. Jag har valt att kalla denna för klass för Post. Först och främst måste du inkludera två “namespaces”.

using System.Xml.XPath;
using System.Xml.Linq;

Själva klassen ska se ut så här:

public string PostId
{
    get;
    set;
}

public string PostedBy
{
    get;
    set;
}

public DateTime DatePosted
{
    get;
    set;
}

public string PostBody
{
    get;
    set;
}

public Post(string postid, string postedby, DateTime dateposted, string post)
{
    this.PostId = postid;
    this.PostedBy = postedby;
    this.DatePosted = dateposted;
    this.PostBody = post;
}

Jag antar att det inte är några konstigheter med ovanstående stycke. Dock vill ju ha möjlighet att spara våra inlägg också och jag har därför skapat tre metoder i denna klass. Det är GetPosts – returnerar alla poster, AddPost – sparar en post samt EditPost vilken givetvis uppdaterar en post. Dessa metoder har jag gjort till static för enkelhetens skull och de ser ut på så här

// Denna metod är bara till lite hjälp så vi slipper skriva samma sak hela tiden
private static XDocument GetXDocument()
{
    return XDocument.Load(HttpContext.Current.Server.MapPath("") + @"/App_Data/posts.xml");
}

public static List<Post> GetPosts()
{
    List<Post> posts;
    
    // Ladda in xmldocumentet
    XDocument xdoc = GetXDocument();
    
    // Med hjälp av LINQ söker vi ut alla post-noder i XML-dokumentet och
    // gör om dem till Post-objekt som vi sedan skapar en lista av.
    posts = (from p in xdoc.Root.Descendants("post")
            select new Post((string)p.Element("PostId"), (string)p.Element("PostedBy"),
                (DateTime)p.Element("DatePosted"), 
(string)p.Element("PostBody"))).ToList<Post>(); return posts; } public static void AddPost(Post p) { // Ladda XML-Documentet XDocument xdoc = GetXDocument(); // Sedan lägger vi till ett nytt element först i dokumentet. // Det vi gör är att vi skapar i root-noden en ny nood vid namn post // som vi sedan fyller på med element samt dess värden. Bodyn skapar // vi som en CDATA-nod så vi kan ha t.ex. < och > i det fältet. // CDATA-elements innehåll parsas inte. xdoc.Root.AddFirst(new XElement("post", new XElement("PostId", p.PostId), new XElement("PostedBy", p.PostedBy), new XElement("DatePosted", p.DatePosted), new XElement("PostBody", new XCData(p.PostBody)))); // Sist men inte minst sparar vi vårt xml-dokument xdoc.Save(HttpContext.Current.Server.MapPath("") + @"/App_Data/posts.xml"); } // Denna metod uppdaterar en post public static void EditPost(string postid, string postbody) { // Ladda XML-dokumentet XDocument xdoc = GetXDocument(); // Hämtar den aktuella noden med hjälp av XPATH XElement node = xdoc.XPathSelectElement("posts/post[PostId='" + postid + "']"); // Uppdaterar den hämtade noden med en ny body node.Element("PostBody").Value = postbody; // Sedan sparar vi åter igen vårat dokument med den // nya informationen xdoc.Save(HttpContext.Current.Server.MapPath("") + @"/App_Data/posts.xml"); }

När detta är klart kan vi öppna upp Default.aspx och där dra ut två textboxar, en knapp samt en repeater. De objekt som jag drog ut namngav jag så här

<asp:TextBox ID="PostedBy" runat="server"></asp:TextBox>
<br />
<asp:TextBox ID="PostBody" runat="server" TextMode="MultiLine"></asp:TextBox>
<br />
<asp:Button ID="Save" runat="server" Text="Posta inlägg" OnClick="Save_Click" />
<br />

<asp:Repeater ID="rptrPosts" runat="server">
<ItemTemplate>
<ul>
<li>Postat av: <%#Eval("PostedBy") %></li>
<li>Datum: <%#Eval("DatePosted") %></li>
</ul>
<div class="Post">
<%#Eval("PostBody") %>
</div>

Det som är kvar att göra nu är att binda datan till repeatern samt skapa klick eventet. För att göra det enklare och mindre redundant kod rekommenderar jag att du skapar en privat metod vid namn BindData där du tar han om databindningen. Då kan du kalla på denna metod varje gång du vill binda om datan istället för att göra det manuellt.

private void BindData()
{
    // Hämtar posterna och binder till repeatern
    rptrPosts.DataSource = Post.GetPosts();
    rptrPosts.DataBind();
}

I Page_Load så binder vi datan om det inte är en postback

if (!IsPostBack)
{
    BindData();
}

och klick-eventet för vår knapp ser ut så här

protected void Save_Click(object sender, EventArgs e)
{
    // När vi klickar på Spara-knappen så lagrar vi informationen i XML-dokumentet
    Post.AddPost(new Post(Guid.NewGuid().ToString(), PostedBy.Text, DateTime.Now, 
PostBody.Text)); // Och binder om datan BindData(); }

Sedan har vi en gästbok som sparar all information i ett XML-dokument. Funktionaliteten för att uppdatera själva XML-arket har jag inte skapat, men det är inga större svårigheter då metoden för det redan är skapad.

Observera att denna gästbok inte har något skydd mot t.ex. XSS, men detta kan du enkelt implementera genom att html-koda den data som användaren har matat in när du hämtar ut datan i metoden GetPosts.

På återseende.

Ladda ner:

Tags: , , ,

Artikel | ASP.NET | C# | XML | Linq

Skapa en gästbok i ASP.NET utan databas

by Reager 7. August 2007 17:32

Läs hellre denna artikel:

http://aspdotnet.nu/post/Skapa-en-gastbok-med-Linq-2-XML.aspx

Här kommer den första artikeln på denna blogg. Denna kommer att visa hur du enkelt skapar dig en gästbok utan någon databas. Istället lagras alla inlägg i en XML-fil. Detta fungerar bra för mindre gästböcker, men är inte att rekommendera för stora siter.

Börja med att skapa en ny ASP.NET Web Site i Visual Studio eller Visual Web Express, beroende på vilket
program du använder.

Vi börjar i Source-läget, det första som behövs är några textboxar som besökaren kan mata in gästboksinlägget i. De
kontroller som behövs är tre textboxar, observera TextMode="MultiLine" den sista, detta gör att textboxen skapas
som en <Textarea>. Sedan så lägger vi till en knapp som vi kopplar ett OnClick-event till.

  1.     <div>
  2.     Namn: <asp:TextBox runat="server" ID="txbName"></asp:TextBox><br />
  3.     E-post: <asp:TextBox runat="server" ID="txbEmail"></asp:TextBox><br />
  4.     Inlägg: <asp:TextBox runat="server" ID="txaMessage" TextMode="MultiLine"></asp:TextBox>
  5.     <asp:Button runat="server" ID="btnSend" Text="Skicka inlägg" OnClick="btnSend_Click" />
  6.     </div>

Gå sedan till Code-läget, du kommer dit genom att högerklicka och välja "View Code". Det första som skall göras är att tala om att vi vill
använda XML-namespacet. Detta gör du genom att högst upp på sidan ange using System.Xml; Nästa steg är att tala om vad som skall hända
när vi trycker på knappen "Skicka inlägg".

  1.             // Vi börjar med att kolla vi har någon gb.xml, har vi det behöver vi inte skapa
  2.             // den igen.
  3.             if (!System.IO.File.Exists(Server.MapPath("App_Data") + @"\gb.xml"))
  4.             {

  5.                 // Vi börjar med att skapa ett objekt av typen XmlWriter som skapar
  6.                 // en XML-fil som vi kan skriva till.
  7.                 XmlWriter writer = XmlTextWriter.Create(Server.MapPath("App_Data") + @"\gb.xml");
  8.                 // Huvudelementet i våran XML-fil skall heta messages, det
  9.                 // är inom denna som vi samlar alla våra inlägg, i xml-filen kallade post
  10.                 writer.WriteStartElement("messages");
  11.                 // Skapar elementet post
  12.                 writer.WriteStartElement("post");
  13.                 // Skapar ett element och skriver namnet i den, de följande raderna
  14.                 // gör motsvarande uppgift.
  15.                 writer.WriteElementString("name", txbName.Text);
  16.                 writer.WriteElementString("email", txbEmail.Text);
  17.                 writer.WriteElementString("date", DateTime.Now.ToString());
  18.                 // För att vi inte ska drabbas av otrevliga html-inlägg eller andra kodsnuttar
  19.                 // i vår gästbok så html-kodar vi det med metoden Server.HtmlEncode,
  20.                 // vilket innebär att alla html-taggar skrivs ut som text. För att de enterslag
  21.                 // som användarna skriver in skall skrivas ut så får vi
  22.                 // "göra om" enterslagen till <br />-taggar som förstås av webbläsaren, vilket utförs med
  23.                 // hjälp av replace, enterslagen hittar vi med System.Environment.Newline.
  24.                 writer.WriteElementString("message", Server.HtmlEncode(txaMessage.Text.Replace(System.Environment.NewLine, "<br />")));
  25.                 // Skriv ut slutet på post
  26.                 writer.WriteEndElement();
  27.                 // Skriv ut slutet på messages
  28.                 writer.WriteEndElement();
  29.                
  30.                 // För att det skall skrivas till filen anropas vi metoden Flush
  31.                 writer.Flush();
  32.                 // Sist men inte minst stänger vi vårat objekt.
  33.                 writer.Close();
  34.                 // Skicka tillbaka oss till förstasidan
  35.                 Response.Redirect("default.aspx");
  36.             }

Så går det till att skapa en XML-fil, och skriva några element till den. Men om vi nu redan har skrivit till
XML-filen så att den redan finns, hur gör vi då? 

  1.             // Om filen redan fanns så får vi gå lite annorlunda till väga.
  2.             else
  3.             {                
  4.                 // Börjar med att skapa ett XmlDocument-objekt som vi laddar
  5.                 // in våran XML-fil till.
  6.                 XmlDocument doc = new XmlDocument();
  7.                 doc.Load(Server.MapPath("App_Data") + @"\gb.xml");
  8.                 // Sedan hämtar vi ut root-elementet, det översta, i detta fall messages
  9.                 XmlElement root = doc.DocumentElement;
  10.                 // Sedan skapar vi en nod som skall heta post, detta bestämde vi i koden
  11.                 // som skapde XML-filen 
  12.                 XmlNode newpost = doc.CreateNode(XmlNodeType.Element, "post", "");
  13.                 // Nästa steg är att skapa de element som skall finnas i vårat post-element, detta
  14.                 // blir name, email, date, och message. Jag förklarar bara det första, då alla fungerar
  15.                 // på samma sätt.
  16.                 // Först skapar vi elementet name
  17.                 XmlElement name = doc.CreateElement("name");
  18.                 // Sedan lägger vi till en Textnod i detta element som child, vilket är
  19.                 // texten som vi vill skall finnas inom name-taggen
  20.                 name.AppendChild(doc.CreateTextNode(txbName.Text));
  21.                 // Sedan lägger vi till detta element till post-elementet.
  22.                 newpost.AppendChild(name);
  23.                 XmlElement email = doc.CreateElement("email");
  24.                 email.AppendChild(doc.CreateTextNode(txbEmail.Text));
  25.                 newpost.AppendChild(email);
  26.                 XmlElement date = doc.CreateElement("date");
  27.                 date.AppendChild(doc.CreateTextNode(DateTime.Now.ToString()));
  28.                 newpost.AppendChild(date);
  29.                 XmlElement mess = doc.CreateElement("message");
  30.                 mess.AppendChild(doc.CreateTextNode(txaMessage.Text.Replace(System.Environment.NewLine, "<br />")));
  31.                 newpost.AppendChild(mess);
  32.                 // För att vi ska få vårat element att hamna överst, vi vill ju såklart
  33.                 // ha våra element sorterade med senaste först så använder vi metoden
  34.                 // InsertBefore på våran root-element (messages), där vi anger vilken post som ska in (newpost)
  35.                 // och före vilket element det skall in, vilket vi får fram med root.FirstChild
  36.                 root.InsertBefore(newpost, root.FirstChild);
  37.                 // Sist men inte minst skall vi spara vårat uppdaterade xml-document.
  38.                 doc.Save(Server.MapPath("App_Data") + @"\gb.xml");
  39.                 // Skicka tillbaka oss till förstasidan
  40.                 Response.Redirect("default.aspx");

Tags: , , ,

Artikel | ASP.NET | C# | XML

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

RecentComments

Comment RSS