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: