ASP.Net MVC: Multiple Checkboxes and Strongly Typed Views

This might be a first, but I actually stole this from myself off Stackoverflow. Posted it and thought it might be useful to share with the 1 live person who reads this blog and the 90 other bots… And I’m not sure about the 1 live person.

So here’s the situation, it’s late, you’ve got a strongly typed view that has a checkbox list, and you are desperate for an answer on how to handle it…. and now you’re scraping the bottom of the barrel. Well, good news is, I have the answer.

Let’s say you have a Book class that has a list of Categories. The Category class is simple, just has an id and name.

  public class Book
  {
    public Int32 BookId { get; set; }
    public IList<Category> Categories { get; set; }
  }

  public class Category
  {
    public Int32 Id { get; set; }
    public String Name { get; set; }
  }

Now you could try and figure out a way to create a typed view using the Book class. You could also stomp on your left foot until it bleeds. Who am I to judge you for liking pain? (Sick f—) For those who don’t want to go through that nightmare, I have an alternative: Create two new classes, one to set the view and one to handle the post back.

public class ViewBookModel
{
  public ViewBookModel(Book book, IList<Categories> categoryList)
  {
    BookId = book.Id;
    CategoryList = categoryList;
  }

  public Int32 BookId { get; private set; }
  IList<Categories> CategoryList { get; set; }
}

First the class to set the view. As you can see, there is a book id that corresponds to a book object’s id (DUH) and the category list which you will set in the original action.

  [AcceptVerbs(HttpVerbs.Get)]
  public ActionResult EditBook(Int32 bookId)
  {
     Book foundBook = Book.GetById(bookId);
     IList<Category> categoryList = Category.GetAll();
     ViewBookModel model = new ViewBookModel(foundBook, categoryList);
     return View(model);
  }

And then your markup for the checkbox list will be something like this:

  <%
    foreach(var category in Model.CategoryList)
    {
  %>
      <input type="checkbox" name="CategoryIds" value="<%= category.Id %>" />
  <%
    }
  %>

Notice that the name for every input is CategoryIds. This is because this will be the name of the collection of ids on the model for posting:

  public class ViewBookInModel
  {
    public String BookId { get; set; }
    public Int32[] CategoryIds { get; set; }
  }

And the action method would look like:

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult UpdateBook(ViewBookInModel book)
  {
    foreach(Int32 id in book.CategoryIds)
    {
      ...
    }
  }

And boom, problem solved. You can now use a strongly typed View with a checkbox list. Go forth and be fruitful.

ASP.Net MVC: PhotoView Lessons – Getting Around A Master Page Model

Original About PhotoView Here

I’ve started to take the PhotoView site and move it toward a full blow site application. Not sure why, but then again why shouldn’t I? Don’t have a good reason? Pbbbbbbtttt jog off.

One thing I ran into yesterday while working on it, as I’ve added authentication to the site (An update I’ll post sometime this week I think), is having a menu show or not show based on the user being logged in or and admin or whatever. What I don’t like doing is having to call methods from the “framework” if I can just add a property to a model. There are various reasons why, ranging from the fact mark up errors don’t blow up compile time to the idea that the model should take care of those things. Now you can’t always follow this rule as it’s obvious I use the CreateUrl method like it’s a bat in a shed. (I have no idea what that means) However, a certain amount of lock down is nice and the Create method is an extension method so it doesn’t look like I’m cheating… Am I right?

So here’s the situation, I would like to have a model that has two properties UserIsLoggedIn and UserIsAdmin so I can do magic like:

  <%
    if(Model.UserIsAdmin)
    {
  %>
      <a href="Admin/DoStuff" > Admin Stuff </a>
  <%
    }
  %>

Now this would seem to be simple, you would think having the master page inherit from the generic version of ViewMastePage:

  Inherits="System.Web.Mvc.ViewMasterPage<SomeModelClass>"

And the class would be something like this:

  public class SomeModelClass()
  {
    public Boolean UserIsAdmin { get; set; }
    public Boolean UserIsLoggedIn { get; set; }
  }

And the flowers would bloom, the sun would shine, and dogs and cats would live in harmony. And it works that way up until you actually run any given page with a strongly typed view. Then you get this error:

Sorry bro, but you need a hella cool model that is all like “Hey mom” to SomeModelClass.

I think I’m paraphrasing a bit but the idea to take from this is that all view models will have to inherit from the same model the master page is using. Yeah, basically a bit “go f— yourself” written into MVC. So either you follow this obviously easy and unhindering design choice or you do what all programmers must do at some point: Compromise. And I mean that in the real sense, not the in the relationship, better to bend than break even though you’re already broken sort of way.

Remember that little bit of self comfort I gave myself for the HtmlHelper extension CreateUrl, well it’s time to do that once again. So in a He’s Just Not That In To You sort of way (Yes I saw that movie. That’s the other version of compromise), I’m going to tell myself that it’s ok and that though it may be bad for most situations, I’ve heard that Sally’s friend in New York who is a programmer got away with it so I’ll most like get away with it too.

  public static class ViewMasterPageExtension
  {
    public static String CurrentUrl(this ViewMasterPage page)
    {
      return SiteMethods.GetCurrentUrl();
    }

    public static Boolean UserIsAdmin(this ViewMasterPage page)
    {
      return State.CurrentUser != null && State.CurrentUser.UserType == PhotoViewUserType.GetAdminType();
    }

    public static Boolean UserIsLoggedIn(this ViewMasterPage page)
    {
      return State.CurrentUser != null;
    }
  }

Yes it’s not on a model, yes it’s a work around, but I’d rather do this:

  if(this.UserIsAdmin())

Than this:

  if(State.CurrentUser != null && State.CurrentUser.UserType == PhotoViewUserType.GetAdminType();)

And in the end, isn’t what make my life easier the main goal of existence?

Is it me or does Sam Neil look beyond creepy in this imdb photo?

ASP.Net MVC: Show Picture Dynamically Using jQuery

Ready for the next step to this guy? Can’t sleep lately because of it? Ignoring your day to day tasks due to anticipation? Well wait no longer. I have just the cure for you. In fact, steady use has shown to improve both self esteem and popularity. Behold Jquepictuax:

function showPicture(imageHolder, id)
{
  jQuery(imageHolder).attr("src", "/Photo/ShowPhoto/" + id);
}

And you can’t forget to try:

<img id="holder" alt="" />
<div onclick="showPicture('#holder', '79');">Show!</div>

And with that your life will be far better than it was before. You can once again start enjoying the simple things in life. Enjoy the birds singing, the sun setting, and those noisy little things that run around your house.

Disclaimer: Id may vary. Image results also very. Though proven to be better when tested again a placebo, Jquepictuax may not improve your self esteem or make you more popular. Jquepictuax is not guaranteed to improve your life in any way. Use Jquepictuax in small quantities. People with low blood pressure or who are pregnant should avoid using Jquepictuax. If you consume more than 3 alcoholic drinks per day, please seek medical attention before use. May cause certain side effects such as dizziness, nausea, overwhelming chills, headaches, muscle soreness, dry mouth, light headedness, sleepiness, drop in appetite, and death. If you notice any these side effects, stop use of Jquepictuax immediately and seek medical attention. Please consult physician before Jquepictuax use.

You happiness is right around the corner, why not turn it with Jquepictuax?

ASP.Net MVC: Upload Image to Database and Show Image “Dynamically” Using a View

Oddly enough this came about from me wanting to do this, figuring it out, and then deciding not to bother with it. So there’s a possibility this will happen to you too. Well that’s not completely true. The first half where I was uploading and showing from a database, but showing an image through a view to mimic the .ashx functionality of WebForms is still pretty useful.

Saving the Image

First off, here’s the look of the table:

Table

So pretty simple table. Most important parts are the ImageData and ContentType. Why? Well let’s look at the action needed to save the image:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Upload(PhotoForSingleItem photo)
{
  //PhotoForSingleItem is just a class that has properties
  // Name and Alternate text.  I use strongly typed Views and Actions
  //  because I'm not a fan of using string to get the posted data from the
  //  FormCollection.  That just seems ugly and unreliable to me.

  //PhotoViewImage is just a Entityframework class that has
  // String Name, String AlternateText, Byte[] ActualImage,
  //  and String ContentType
  PhotoViewImage newImage = new PhotoViewImage();
  HttpPostedFileBase file = Request.Files["OriginalLocation"];
  newImage.Name = photo.Name;
  newImage.Alt = photo.AlternateText;

  //Here's where the ContentType column comes in handy.  By saving
  //  this to the database, it makes it infinitely easier to get it back
  //  later when trying to show the image.
  newImage.ContentType = file.ContentType;

  Int32 length = file.ContentLength;
  //This may seem odd, but the fun part is that if
  //  I didn't have a temp image to read into, I would
  //  get memory issues for some reason.  Something to do
  //  with reading straight into the object's ActualImage property.
  byte[] tempImage = new byte[length];
  file.InputStream.Read(tempImage, 0, length);
  newImage.ActualImage = tempImage ;

  newImage.Save();

  //This part is completely optional.  You could redirect on success
  // or handle errors ect.  Just wanted to keep this simple for the example.
  return View();
}

And here’s the mark up to get this ball a rollin’:

<form method="post" enctype="multipart/form-data" action="Photo/Upload">
  <div>
    <span>
     Name:
   </span>
   <span>
     <input type="text" id="Name" name="Name" />
   </span>
  </div>
  <div>
    <span>
      Alternate Text:
    </span>
    <span>
     <input type="text" id="AlternateText" name="AlternateText" />
    </span>
  </div>
  <div>
    <span>
      Image
    </span>
    <span>
      <input type="file" id="OriginalLocation" name="OriginalLocation" />
    </span>
  </div>
  <div>
    <input type="submit" value="Upload" />
  </div>
</form>

Biggest thing to notice in the markup is the enctype=”multipart/form-data”. This is a must to upload images. It was something I was missing originally and annoyed the hell out of me.

Showing the Image

So now that we have a we to upload the image, how the hell do you use it? Well that’s not too hard. It just involves a new type of result, an action, and an img element.

So the first thing you need is an image result, and in using my superior intellect I came up with such a thing. And by superior intellect I mean I used StackOverflow. Oddly enough though, it’s actually the second post that I got it from and I changed it a little. However, it was very useful.

using System.Web;
using System.Web.Mvc;
using System.IO;

public class ImageResult : ActionResult
{
  public String ContentType { get; set; }
  public byte[] ImageBytes { get; set; }
  public String SourceFilename { get; set; }

  //This is used for times where you have a physical location
  public ImageResult(String sourceFilename, String contentType)
  {
    SourceFilename = sourceFilename;
    ContentType = contentType;
  }

  //This is used for when you have the actual image in byte form
  //  which is more important for this post.
  public ImageResult(byte[] sourceStream, String contentType)
  {
    ImageBytes = sourceStream;
    ContentType = contentType;
  }

  public override void ExecuteResult(ControllerContext context)
  {
    var response = context.HttpContext.Response;
    response.Clear();
    response.Cache.SetCacheability(HttpCacheability.NoCache);
    response.ContentType = ContentType;

    //Check to see if this is done from bytes or physical location
    //  If you're really paranoid you could set a true/false flag in
    //  the constructor.
    if (ImageBytes != null)
    {
      var stream = new MemoryStream(ImageBytes);
      stream.WriteTo(response.OutputStream);
      stream.Dispose();
    }
    else
    {
      response.TransmitFile(SourceFilename);
    }
  }
}

And here’s how you use the actual result.

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult ShowPhoto(Int32 id)
{
  //This is my method for getting the image information
  // including the image byte array from the image column in
  // a database.
  PhotoViewImage image = PhotoViewImage.GetById(id);
  //As you can see the use is stupid simple.  Just get the image bytes and the
  //  saved content type.  See this is where the contentType comes in real handy.
  ImageResult result = new ImageResult(image.ActualImage, image.ContentType);

  return result;
}

And the markup would go a little sumthin’ like dis:

  <img src="/Photo/ShowPhoto/1" alt="" />

And now you too can upload an image to a database, show it, and then decide just to physically host the images anyway. Next post will be about how to use this with jQuery and asynchronously. I bet you can’t wait!

jQuery: Holy Smokes I Like This Link

Good old Stackoverflow. Wasn’t sure how to post this without looking like I’m trying to get search engine hits. However, wanted to pass this one on anyhow.

How to center a div using jQuery.

Have used it. Works brilliantly. Although the:

  this.css("position","absolute");

May be overkill since any “pop up” div I create already has that in the style where personally I think it should be.

How does it work? Well break down the “top” part:

  this.css("top", ( jQuery(window).height() - this.height() ) / 2+jQuery(window).scrollTop() + "px");

To

   jQuery(window).height() - this.height() ) / 2

But why not just divide the height by 2? Well say the height of the window is 800 and your item is 600 high. If you just placed the item at 800 / 2, the bottom of the item would end up 1000. (800/2 = 400… 600 tall item + 400 starting point = 1000). So subtracting the item’s height from the window height and THEN dividing by two ensures that that item, provided it is no taller than the window, will end up within the 800 tall window.

  + jQuery(window).scrollTop()

Now what if the user has scrolled the widow down? Well adjust for that. using the scrollTop(), the item can be started at the correct point adjusted with the scroll. Nice huh?