Using Cloud Storage with .NET

This part of the .NET Bookshelf tutorial shows how to store images in Google Cloud Storage.

This page is part of a multi-page tutorial. To start from the beginning and see instructions for setting up, go to .NET Bookshelf App.

Creating a Cloud Storage bucket

The following instructions show how to create a Cloud Storage bucket. Buckets are the basic containers that hold your data in Cloud Storage.

To create a bucket:

  1. Invoke the following command in a terminal window:

    gsutil mb gs://[YOUR-BUCKET-NAME]

  2. Set the bucket's default ACL to public-read, which enables users to see their uploaded images:

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

Configuring settings

  1. In the getting-started-dotnet\aspnet\3-binary-data directory, double click 3-binary-data.sln to open the sample app in Visual Studio.

  2. In the Solution Explorer pane, click Web.config.

  3. In Web.config:

    • Set GoogleCloudSamples:ProjectId to your project ID.

    • Set the value of GoogleCloudSamples:BookStore to the same value you used during the Using Structured Data part of this tutorial.

    • If you used Cloud SQL or SQL Server during the structured data step, find the <connectionStrings> XML element and set the connectionString to the same value you used during that step.

    • Set GoogleCloudSamples:BucketName to the name of the Cloud Storage bucket you created previously.

  4. Save and close Web.config.

Running the app on your local machine

In Visual Studio, press F5 to run the project. Now you can browse the app's web pages, add books with cover images, edit books, and delete books.

Deploying the app to Compute Engine

  1. In Visual Studio, in the Solution Explorer pane, right click 3-binary-data, and choose Publish. Publish application

  2. Create a new custom profile as you did in the Using Structured Data part of this tutorial.

  3. Click Publish.

Application structure

Binary data sample structure

The application uses Cloud Storage to store binary data, pictures in this case. It continues to use a structured database for the book information: Cloud Datastore, Cloud SQL, or SQL Server. The browser fetches images directly from Cloud Storage.

Understanding the code

This section walks you through the application code and explains how it works.

Handling user uploads

The form has a new <input type="file"> tag so the user can upload a file:

<div class="form-group">
    @Html.Label("Cover Image")
    <input type="file" id="image" name="image" value="@Model.Book.ImageUrl" class="form-control">
    @Html.HiddenFor(model => model.Book.ImageUrl)

Uploading to Cloud Storage

The BooksController.Create() method now uploads the image:

// POST: Books/Create
public async Task<ActionResult> Create(Book book, HttpPostedFileBase image)
    if (ModelState.IsValid)
        // If book cover image submitted, save image to Cloud Storage
        if (image != null)
            var imageUrl = await _imageUploader.UploadImage(image, book.Id);
            book.ImageUrl = imageUrl;
        return RedirectToAction("Details", new { id = book.Id });
    return ViewForm("Create", "Create", book);

The ImageUploader class invokes the Google.Apis.Storage.v1.ClientWrapper.StorageClient API to upload the image:

_storageClient = StorageClient.Create();
        public async Task<String> UploadImage(HttpPostedFileBase image, long id)
            var imageAcl = PredefinedObjectAcl.PublicRead;

            var imageObject = await _storageClient.UploadObjectAsync(
                bucket: _bucketName,
                objectName: id.ToString(),
                contentType: image.ContentType,
                source: image.InputStream,
                options: new UploadObjectOptions { PredefinedAcl = imageAcl }

            return imageObject.MediaLink;

Serving images from Cloud Storage

Because the app has the public URL for the image, serving the image is straightforward. Serving directly from Cloud Storage is helpful, because the requests leverage Google’s global serving infrastructure, and the application doesn’t have to respond to requests for images. This frees up CPU cycles for other requests.

<img class="book-image"
     src="@(String.IsNullOrEmpty(Model.ImageUrl) ?
"" : Model.ImageUrl)">
Was this page helpful? Let us know how we did:

Send feedback about...