Pyrrho's new REST API works well with ASP.NET. This sample was originally
implemented using LocalDB/SQL Server and the Entity Framework. Pyrrho has some
features that are much easier to use, as this sample shows.
Visual Studio uses its own IIS, and for this sample the Pyrrho server needs to be running, with its HTTP service and Pyrrho service. It is not a simple matter to copy or deploy ASP.NET applications, and there are several web sites that discuss how to do so. To make it easier to deploy, you could use EmbeddedPyrrho and the real IIS from the start, but then you have to add more configuration steps during development.
We are still using SQL Server for the ASP.NET account control. You may find yourself accessing the DefaultConnection (Haikus) through Visual Studio’s Server Explorer to remove entries from AspNetUsers.
We will not use the Entity Framework. In my arrogant opinion, client side DataSets and data models are really bad for any form of concurrency and transaction management, and in this respect are a serious error in both the Microsoft and Java world. Instead I invite readers to examine direct use of an database Connection as in step 10 below, to Post (step 12) a strongly-typed class whose structure has been obtained from the DBMS. There are Get, Put and Delete too of course, and this sample will show their use. Put is in step 20, and Get and Delete will be in the next part of this posting. Post automatically supplies any missing components for a new primary key. We will use BLOBs for icons and author pictures.
Visual Studio uses its own IIS, and for this sample the Pyrrho server needs to be running, with its HTTP service and Pyrrho service. It is not a simple matter to copy or deploy ASP.NET applications, and there are several web sites that discuss how to do so. To make it easier to deploy, you could use EmbeddedPyrrho and the real IIS from the start, but then you have to add more configuration steps during development.
We are still using SQL Server for the ASP.NET account control. You may find yourself accessing the DefaultConnection (Haikus) through Visual Studio’s Server Explorer to remove entries from AspNetUsers.
We will not use the Entity Framework. In my arrogant opinion, client side DataSets and data models are really bad for any form of concurrency and transaction management, and in this respect are a serious error in both the Microsoft and Java world. Instead I invite readers to examine direct use of an database Connection as in step 10 below, to Post (step 12) a strongly-typed class whose structure has been obtained from the DBMS. There are Get, Put and Delete too of course, and this sample will show their use. Put is in step 20, and Get and Delete will be in the next part of this posting. Post automatically supplies any missing components for a new primary key. We will use BLOBs for icons and author pictures.
1. Start up VS Express 2013 as administrator,
and from the start Page, select New project. Make sure Visual C# and Web is
selected. Give the Name as Haikus, and make sure the location is somewhere suitable such as C:\Temp.Click OK.
2. Select
MVC, and keep the the other defaults. Click OK
3. After a few minutes, you get an empty project. Try Run. A browser starts up to
access your MVC app running on your local machine. This is the default MVC 5
application. It has many features, but don’t touch them just now. Close the browser window.
Build the underlying database
5. Make sure the Pyrrho server OSP.exe is running, we assume on localhost with the default port 5433.
From a command prompt, start up the PyrrhoCmd utility for
the database haikus: PyrrhoCmd haikus
and enter the commands shown to create the database tables we will use.
The square brackets here help with line
wraparound.
[create
table author(id char primary key,name char,pic blob)]
[create
table verse(id int primary key,ownr char references author,cont char)]
[create table tag(id int primary key,name
char)]
[create
table rating(vid int references verse,uid char references author,score int)]
[create
table tagging(tid int references tag,vid int references verse)]
[create
table comment(id int primary key,vid int references verse,aid char references
author, cont char)]
[create
table likes(vid int references verse,uid char references author)]
6. Still at the SQL prompt, use
the command: table “Role$Class”, to get class definitions for our application.
“Your
mileage may vary”: the Schema keys may be different for you. They are used in
Pyrrho’s REST API to check that the class definition remains valid in the
database and role.
In the command prompt, right click and Select All, then Enter to copy the text to the clipboard, and paste it into a notepad.
We will use each of the class definitions to
define classes AUTHOR, VERSE etc. in the next step.In the command prompt, right click and Select All, then Enter to copy the text to the clipboard, and paste it into a notepad.
7. Back
in Visual Studio, in Solution Explorer, right-click References, Add Reference.. and Browse.. to add OSPLink.dll from the Pyrrho distribution. Click Add.
8. In Solution Explorer, right-click Models select Add/New Item../Visual C#/Code/Class, change the Name to AUTHOR.cs and click Add.
8. In Solution Explorer, right-click Models select Add/New Item../Visual C#/Code/Class, change the Name to AUTHOR.cs and click Add.
9. In the AUTHOR class, paste in the
class definition from AUTHOR that you obtained in step 6.
10. Add
another Models class called Connect and edit it to look like this.
using System;namespace Haikus.Models{using Pyrrho;public class Connect{public static PyrrhoConnect conn;internal Connect(){conn = new PyrrhoConnect("Files=haikus");conn.Open();}}}
11. Open
the Startup.cs file and add a call to make the connection to the database as
shown
12. Now let’s start wiring this up. Any time that a user registers a new account, we want to record them in the Author table.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
new Models.Connect();
ConfigureAuth(app);
}
}12. Now let’s start wiring this up. Any time that a user registers a new account, we want to record them in the Author table.
internal static AUTHOR Find(string us){var au = Connect.conn.FindOne<AUTHOR>(us);if (au != null)return au;au = new AUTHOR { ID = us };Connect.conn.Post(au);return au;}
13. In Solution Explorer, double-click
Controllers>AccountController.cs. Use the drop-down boxes to find the
Register(RegisterViewModel model) method and add the line AUTHOR.Find(..) shown.
[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task<ActionResult> Register(RegisterViewModel model){if (ModelState.IsValid){ var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };IdentityResult result = await UserManager.CreateAsync(user, model.Password);if (result.Succeeded){await SignInAsync(user, isPersistent: false);// For more information on how to enable account …..// ...AUTHOR.Find(user.UserName);return RedirectToAction("Index", "Home");}else{AddErrors(result);}}// If we got this far, something failed, redisplay formreturn View(model);}
14. Before we run the program, in Solution Explorer, left-click the project. In the Properties pane, ensure that
WindowsAuthentication is Disabled and AnonymousAuthentication is Enabled.
15. When you are returned to the home page, verify that you have a welcome message for your new user. Close the browser. In the command prompt we had before, do “table author” to see that fred got defined by the code we added.
Add the following code two closing braces in
from the end of AccountController:
Run the program, and register a
user called fred@abc.com with password Pa$$w0rd.
Click Register and close the browser.15. When you are returned to the home page, verify that you have a welcome message for your new user. Close the browser. In the command prompt we had before, do “table author” to see that fred got defined by the code we added.
Author Profule Pictures
16. Let’s show pictures for logged-in users. We’ll add a URL for this in the AccountController. We’ll create a default image to use if the user hasn’t given a picture. In AccountController.cs add using System.Drawing; and using System.IO; Add this code two closing braces before the end of AccountController.cs:17. Now replace the Hello greeting with the user's picture:[AllowAnonymous]public ActionResult Picture(string id){var au = AUTHOR.Find(id);var b = au.PIC;if (b==null){var im = new Bitmap(24, 24);using (var g = Graphics.FromImage(im)){g.FillRectangle(Brushes.White, new Rectangle(0, 0, 24, 24));g.DrawEllipse(Pens.Black, new Rectangle(6, 6, 12, 12));g.DrawLine(Pens.Black, 2, 22, 7, 17);g.DrawLine(Pens.Black, 22, 22, 17, 17);}var ms = new MemoryStream();im.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);b = ms.ToArray();}return File(b, "image/jpg");}
18. Now let’s start to provide a way for authors to add their profile picture. In Views/Manage/Index.cshtml add the following code somewhere sensible:@using Microsoft.AspNet.Identity@if (Request.IsAuthenticated){using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })){var id = User.Identity.Name;@Html.AntiForgeryToken()<ul class="nav navbar-nav navbar-right"><li><a href="@Url.Action("Index","Manage")"> <img title="@id" alt="@id" src="@("/Account/Picture/'" + id + "'/")" /> @id</a></li>
19. We need to handle the postback.<legend>Choose a profile picture:</legend>@using (Html.BeginForm("Profile", "Account", FormMethod.Post, new { enctype = "multipart/form-data" })){<input type="file" name="file" /><input type="submit" value="Upload Picture" />}
// This action handles the form POST and the upload///
/// A user has just updated their profile picture///
///
///
[HttpPost]
public new ActionResult Profile(HttpPostedFileBase file)
{
var del = new System.Drawing.Image.GetThumbnailImageAbort(dummy);
IntPtr p = new IntPtr();
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
var sr = file.InputStream;
var im = System.Drawing.Image.FromStream(sr);
if (im.Width>24 || im.Height>24)
im = im.GetThumbnailImage(24, 24, del, p);
var ms = new MemoryStream();
im.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
Haikus.Models.AUTHOR.SetPicture(User.Identity.Name,ms.ToArray());
}
// redirect back to the index action to show the
form once again
return RedirectToAction("../Home/Index");
}
// Kludge for GetThumbnail
bool dummy()
{
return false;
}20. Finally define the SetPicture method in the AUTHOR.cs class: Next steps - in Part 2: Editing Haikus, Likes and Comments.internal static void SetPicture(string user, byte[] pic){var au = Find(user);au.PIC = pic;Connect.conn.Put(au);}