ASP. NET MVC upload image from MVC Advanced Programming page No. 311

Source: Internet
Author: User
Tags table definition

Image uploads

I am going to complete the SportsStore user experience with something a little more sophisticated:i would add the ability For the

Administrator to upload product images and store them in the database so that they is displayed in the product catalog. This isn ' t

Something that's especially interesting or useful in its own right, but it does allow me to demonstrate some important MV C

Framework features.

Extending the Database

Open the Visual Studio Server Explorer window and navigate to the Products table in the database created in

Chapter 7. The name of the data connection may has changed to being Efdbcontext, which is the name assigned to the

Connection in the Web. config file. Visual Studio is a little bit inconsistent on when it renames the connection

might also see the original name is shown when the connection is created. Right-click on the Products table and

Select New Query from the pop-up menu and enter the following SQL to the text area:

ALTER TABLE [dbo]. [Products]

ADD [ImageData] VARBINARY (MAX) NULL,

[Imagemimetype] VARCHAR () NULL;

Click the Execute button (which is marked with a arrow) in the Top-left cover of the window and Visual Studio would update

The database, adding the new columns to the table. To test the update, right-click the "Products" table in the Server

Explorer window and select Open Table Definition from the menu. You'll see that there is now columns

Called ImageData and Imagemimetype, as shown in Figure 12-3.

Tip If the columns is not visible, close the design window, right-click on the data connection in the Server

Explorer window and select Refresh from the menu. The new columns should now is visible when you select the

Open Table Definition menu item again.

Enhancing the Domain Model

I need to add II new fields to the products class in the Sportsstore.domain project, correspond to the new

Database columns, as shown in Listing 12-10.

Listing 12-10. Adding Properties in the Product.cs File

Using System.ComponentModel.DataAnnotations;

Using SYSTEM.WEB.MVC;

Namespace SportsStore.Domain.Entities {

public class Product {

[Hiddeninput (Displayvalue = False)]

public int ProductID {get; set;}

[Required (errormessage = "Please enter a product name")]

public string Name {get; set;}

[DataType (Datatype.multilinetext)]

[Required (errormessage = "Please enter a description")]

public string Description {get; set;}

[Required]

[Range (0.01, double. MaxValue, errormessage = "Please enter a

Positive price ")]

Public decimal price {get; set;}

[Required (errormessage = "Please specify a category")]

public string Category {get; set;}

Public byte[] ImageData {get; set;}

public string Imagemimetype {get; set;}

}

}

Caution Make sure, the names of the properties, the add to the Product class exactly match the names you gave

The new columns in the database.

Creating the Upload User Interface Elements

The next step is to add support for handling file uploads. This involves creating a UI, the administrator can use, upload an

Image. Modify The views/admin/edit.cshtml view so it matches Listing 12-11.

Listing 12-11. Adding support for Images in the edit.cshtml File

@model SportsStore.Domain.Entities.Product

@{

312

Viewbag.title = "Admin:edit" + @Model. Name;

Layout = "∼/views/shared/_adminlayout.cshtml";

}

<div class= "Panel" >

<div class= "Panel-heading" >

</div>

@using (Html.BeginForm ("Edit", "Admin",

FormMethod.Post, new {enctype = "multipart/form-data"})) {

<div class= "Panel-body" >

@Html. hiddenfor (M = m.productid)

@foreach (Var property in ViewData.ModelMetadata.Properties) {

Switch (property. PropertyName) {

Case "ProductID":

Case "ImageData":

Case "Imagemimetype":

Do nothing

Break

Default

<div class= "Form-group" >

<label>@ (property. DisplayName??

Property. PropertyName) </label>

@if (property. PropertyName = = "Description") {

@Html. TextArea (property. PropertyName, NULL,

New {@class = "Form-control", rows = 5})

} else {

@Html. TextBox (property. PropertyName, NULL,

New {@class = "Form-control"})

}

@Html. Validationmessage (property. PropertyName)

</div>

Break

}

}

<div class= "Form-group" >

<div style= "position:relative;" >

<label>Image</label>

<a class= ' btn ' href= ' javascript:; ' >

Choose File ...

<input type= "File" Name= "Image" size= "40"

Style= "position:absolute;z-index:2;top:0;

Left:0;filter:alpha (opacity=0); opacity:0;

BackgroundColor:

transparent;color:transparent; "

Onchange= ' $ ("#upload-fileinfo").

HTML ($ (this). Val ()); ' >

</a>

<span class= ' label Label-info ' id= "Upload-file-info" >

</span>

</div>

@if (Model.imagedata = = null) {

313

<div class= "form-control-static" >no image</div>

} else {

Src= "@Url. Action (" GetImage "," Product ",

New {Model.productid}) "/>

}

</div>

</div>

<div class= "Panel-footer" >

<input type= "Submit" value= "Save" class= "btn btn-primary"/>

@Html. ActionLink ("Cancel and Return to List", "Index", NULL, new {

@class = "Btn Btn-default"

})

</div>

}<

/div>

Already be aware that Web browsers would upload files properly only if the HTML form element defines an

Enctype value of Multipart/form-data. In other words, for a successful upload, the form element must look

Like this:

...

<form action= "/admin/edit" enctype= "Multipart/form-data" method= "POST" >

...

Without the Enctype attribute, the browser would transmit only the name of the file and not its content, which are no use at All.

To ensure this enctype attribute appears, I must use a overload of the Html.BeginForm helper method that lets

Me specify HTML attributes, like this:

...

@using (Html.BeginForm ("Edit", "Admin",

FormMethod.Post, new {enctype = "multipart/form-data"})) {

...

There is and changes in the view. The first is that I had replaced the Razor if expression I used when generating

Input elements with a switch statement. The effect is the same and it allows me to specify the model properties I want to

Skip more concisely, and I don ' t want to display the image-related properties directly to the user.

Instead, I had made the remaining change, which was to add an INPUT element whose type was file to allow file upload, along

With an IMG element to display the image associated with a product, if there are one in the database.

The horrific mess of inline CSS and JavaScript addresses a shortcoming in the Bootstrap library:it does not properly styl E file

Input elements. There is a number of extensions that add the missing functionality and I have chosen the magic incantation

Shown in the listing because it's self-contained and is reliable. It doesn ' t change the the-the-the-the-MVC Framework works, just the

The which the elements in the edit.cshtml file is styled.

Saving Images to the Database

I need to enhance the POST version of the "Edit" action method in the Admin controller so that I take the image data that ha S

been uploaded and save it in the database. Listing 12-12 shows the changes that is required.

Listing 12-12. Handling Image Data in the AdminController.cs File

Using System.Linq;

Using System.Web;

Using SYSTEM.WEB.MVC;

Using SportsStore.Domain.Abstract;

314

Using SportsStore.Domain.Entities;

Namespace SportsStore.WebUI.Controllers {

[Authorize]

public class Admincontroller:controller {

Private Iproductrepository repository;

Public Admincontroller (Iproductrepository repo) {

repository = repo;

}

Public ViewResult Index () {

Return View (repository. Products);

}

Public ViewResult Edit (int productId) {

Product Product = Repository. Products

. FirstOrDefault (p = P.productid = = ProductID);

return View (product);

}

[HttpPost]

Public ActionResult Edit (product product, HttpPostedFileBase image

= null) {

if (modelstate.isvalid) {

if (image! = null) {

Product. Imagemimetype = image. ContentType;

Product. ImageData = new Byte[image. ContentLength];

Image. Inputstream.read (product. ImageData, 0,

Image. ContentLength);

}

Repository. Saveproduct (product);

tempdata["message"] = string. Format ("{0} has been saved",

Product. Name);

Return redirecttoaction ("Index");

} else {

There is something wrong with the data values

return View (product);

}

}

Public ViewResult Create () {

Return View ("Edit", New Product ());

}

[HttpPost]

Public ActionResult Delete (int productId) {

Product deletedproduct = Repository. Deleteproduct (PRODUCTID);

if (deletedproduct! = null) {

tempdata["message"] = string. Format ("{0} was deleted",

Deletedproduct.name);

}

Return redirecttoaction ("Index");

}

315

}

}

I have added a new parameter to the Edit method, which the MVC Framework uses to pass the uploaded file data to the

Action method. I Check to see if the parameter value is null; If it isn't, I copy the data and the MIME type from the parameter

To the Product object so it's saved to the database. I must also update the Efproductrepository class in the

Sportsstore.domain project to ensure, the values assigned to the ImageData and Imagemimetype

Properties is stored in the database. Listing 12-13 shows the required changes to the Saveproduct method.

Listing 12-13. Ensuring that the Image Values is Stored in the Database in the EFProductRepository.cs File

...

public void Saveproduct (product product) {

if (product. ProductID = = 0) {

Context. Products.add (product);

} else {

Product dbentry = context. Products.find (product. ProductID);

if (dbentry! = null) {

Dbentry.name = product. Name;

Dbentry.description = product. Description;

Dbentry.price = product. Price;

Dbentry.category = product. Category;

Dbentry.imagedata = product. ImageData;

Dbentry.imagemimetype = product. Imagemimetype;

}

}

Context. SaveChanges ();

}.

..

Implementing the GetImage Action Method

In Listing 12-11, I added an IMG element whose content is obtained through a GetImage action method on the

Product Controller. I am going to implement this action method so I can display images contained in the database. Listing

12-14 shows the definition of the action method.

Listing 12-14. The GetImage Action Method in the ProductController.cs File

Using System;

Using System.Collections.Generic;

Using System.Linq;

Using System.Web;

Using SYSTEM.WEB.MVC;

Using SportsStore.Domain.Abstract;

Using SportsStore.Domain.Entities;

Using SportsStore.WebUI.Models;

Namespace SportsStore.WebUI.Controllers {

public class Productcontroller:controller {

Private Iproductrepository repository;

public int PageSize = 4;

Public Productcontroller (Iproductrepository productrepository) {

316

This.repository = productrepository;

}

Public ViewResult List (string category, int page = 1) {

Productslistviewmodel model = new Productslistviewmodel {

Products = Repository. Products

. Where (p = category = = NULL | | p.category = =

Category

. (p = p.productid)

. Skip ((page-1) * PageSize)

. Take (PageSize),

Paginginfo = new Paginginfo {

currentpage = page,

ItemsPerPage = PageSize,

TotalItems = Category = = null?

Repository. Products.count ():

Repository. Products.where (E = E.category = =

category). Count ()

},

Currentcategory = Category

};

return View (model);

}

Public Filecontentresult GetImage (int productId) {

Product prod = repository. Products

. FirstOrDefault (p = P.productid = = ProductID);

if (prod! = null) {

Return File (prod. ImageData, prod. Imagemimetype);

} else {

return null;

}

}

}

}

This method tries to find a product, matches the ID specified by the parameter. The Filecontentresult class is

Used as the result from an action method when you want to return a file to the client browser, and instances is created U Sing the

File

ASP. Upload images from MVC Advanced Programming page No. 311

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.