[Dev Tip] Wrap HttpPostedFileStream for unit test,…


using System.IO;
using System.Web;

namespace Hydra.Insurance.Web.Helpers
{
public class HttpPostedFileStreamWrapper : HttpPostedFileBase
{
private string contentType;
private string filename;
private Stream inputStream;

public HttpPostedFileStreamWrapper(Stream inputStream, string contentType = null, string filename = null)
{
this.inputStream = inputStream;
this.contentType = contentType;
this.filename = filename;
}

public override int ContentLength
{
get
{
return (int)inputStream.Length;
}
}

public override string ContentType
{
get
{
return contentType;
}
}

public override string FileName
{
get
{
return filename;
}
}

public override Stream InputStream
{
get
{
return inputStream;
}
}

public override void SaveAs(string filename)
{
using (var stream = File.OpenWrite(filename))
{
InputStream.CopyTo(stream);
}
}
}
}

[Dev tip] Per request lifetime management for UserManager class in ASP.NET Identity

Introduction

We recently released the 2.0.0-beta1 version of ASP.NET Identity. Learn more here by visiting this link. This is an update to 2.0.0-alpha1 and adds the two-factor auth feature along with a few bug fixes. To learn more about the Alpha release, please visit this link.

In this article I am going to explain the significance of the UserManager class in an application and some of the best practices when using it. I am going to use an MVC application that is created using VS 2013 RTM. In the Visual Studio 2013 RTM templates, which had the 1.0.0 version of ASP.NET Identity, we demonstrated directly instantiating the UserManager class as needed in the application. This approach had a few issues, which are explained further in this article. These have been fixed in 2.0.0-beta1.

Understanding Managers and Stores

ASP.NET Identity consists of classes called managers and stores. Managers are high-level classes which an application developer uses to perform operations in the ASP.NET Identity system, such as creating a user. Stores are lower-level classes that specify how entities, such as users and roles, are persisted. Stores are closely coupled with the persistence mechanism, but managers are decoupled from stores which means you can replace the persistence mechanism without disrupting the entire application.

The current article outlines the steps to configure the UserManager in the application. We will start with an application with Identity 1.0.0. We will migrate the solution to 2.0.0-beta1, and change the way UserManager is instantiated and used in the application. Additionally, with this approach it is possible to configure the properties on the UserManager, such as password length and complexity.

Create Application

In Visual Studio 2013 RTM create a new web application. Choose MVC

clip_image002

UserManager explained

Let us briefly look at how the UserManager class is used in the application. All user account management actions are defined in the AccountController class.

Code Snippet
  1. public AccountController()
  2.             : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
  3.         {
  4.         }
  5.         public AccountController(UserManager<ApplicationUser> userManager)
  6.         {
  7.             UserManager = userManager;
  8.         }
  9.         public UserManager<ApplicationUser> UserManager { get; private set; }

The controller has a UserManager property of type UserManager which is set in the constructor. The UserManager class takes in an instance of UserStore class which implements operations on the user that are persistence-specific. In our case, we have a UserStore class which implements these operations specific to EntityFramework. To persist data to/from the database the UserStore class takes in an instance of DBContext class. The UserStore class is defined in the Microsoft.AspNet.Identity.EntityFramework assembly.

Note: The rationale behind implementing this pattern is that if the developer wishes to store user information in the any other storage system (for example, Azure Table storage), all they have do is replace the ‘UserStore’ class with an Azure Table storage implementation. There would be no additional changes needed in the AccountController, and the existing application would function seamlessly.

The problem

In the current approach, if there are two instances of the UserManager in the request that work on the same user, they would be working with two different instances of the user object. An example for this would be using the one in the class property and instantiating one locally in the method under execution. In this scenario the changes made by either of them would not reflect the changes made by the other. Hence persisting these changes back to the database would lead to incorrect changes being made to the user object.

The same problem exists when you are trying to use the DBContext class in the application.

The solution

The solution to the above problem is to store a single instance of UserManager and DbContext per request and reuse them throughout the application. Since Identity hooks into the OWIN pipeline via cookie middleware, we can store the UserManager and DbContext in the OWIN context object and retrieve them as needed.

1. In the application created above, update the Identity packages to 2.0.0-beta1 from the NuGet feed. This can be done through the Manage Nuget packages window. The steps to update Nuget packages are explained here.

2. Instead of directly working with UserManager<T> class we can define a custom class, ApplicationUserManager that extends from UserManager<T>. In the project under the App_Start folder create a new file IdentityConfig.cs and add a new class ApplicationUserManager. The ApplicationUserManager should extend the UserManager class

Code Snippet
  1. public class ApplicationUserManager : UserManager<ApplicationUser>
  2.     {
  3.     }

3. The web application uses the new OWIN cookie middleware for the cookie-based authentication. During application start, the Configuration method in the Startup class is invoked, which configures all the middleware components registered in the application. In the MVC 5 template, the cookie middleware is configured through the ConfigAuth method defined in the Startup.Auth class.

Since we need to register the UserManager and DBContext class with the OWIN context during app start, we will add methods to do that in the ConfigureAuth method. The ‘CreatePerOwinContext<T>’ method is defined in the Microsoft.AspNet.Identity.Owin namespace. This method registers a static callback method which returns an instance of type <T>. This method is invoked once per request and used to obtain instance object which is used during the lifetime of the request.

4. To create a static callback method that returns an instance of DbContext , in the ApplicationDbContext class create a method as defined below

Code Snippet
  1. public static ApplicationDbContext Create()
  2.     {
  3.         return new ApplicationDbContext();
  4.     }

5. Similarly define a method in the ApplicationUserManager that returns an instance of the ApplicationUserManager.

Code Snippet
  1. public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
  2.         {
  3.             var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
  4.             return manager;
  5.         }

In the constructor of the UserManager, we need to retrieve the instance of DbContext to configure the UserStore. We can get the instance of the object from the OwinContext using the ‘Get<ApplicationDbContext>’ method that in turn returns the single instance of DbContext class created using ApplicationDbContext.Create callback method.

6. Register these two callback methods in the ConfigureAuth method through the ‘CreatePerOwinContext’ method

Code Snippet
  1. public void ConfigureAuth(IAppBuilder app)
  2.         {
  3.         app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create);
  4.         app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
  5.          .
  6.          }

7. Next we hook this up in the AccountController class. Change the constructor and the UserManager property on the class to type ApplicationUserManager

Code Snippet
  1. public AccountController()
  2.         {
  3.         }
  4.         public AccountController(ApplicationUserManager userManager)
  5.         {
  6.             UserManager = userManager;
  7.         }
  8.         private ApplicationUserManager _userManager;
  9.         public ApplicationUserManager UserManager
  10.         {
  11.             get;
  12.             private set;
  13.         }

8. In the set property of the UserManager we need can retrieve the UserManager instance from the OWIN context. For this we have an extension method provided in the Microsoft.AspNet.Identity.Owin namespace

Code Snippet
  1. public ApplicationUserManager UserManager
  2.         {
  3.             get
  4.             {
  5.                 return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
  6.             }
  7.             private set
  8.             {
  9.                 _userManager = value;
  10.             }
  11.         }

9. Run the application and verify that a local user can be created in the application.

10. Also in the application if we need to work with the DbContext object directly we can get the instance of the class from the OWIN context as mentioned earlier using the ‘Get<T>’ method

Code Snippet
  1. var dbContext = context.Get<ApplicationDbContext>();

Configuring UserManager properties

Another advantage of following this approach is that we can configure the UserManager properties when instantiating it in a single place. For example, the UserManager by default has a password validator that validates that the supplied password is of length 6 characters. We can change this to use the new password validator in 2.0.0-beta1 which checks for additional complexity in the supplied password during registration.

To do this, simply set the PasswordValidator property in the ‘Create’ method of the ApplicationUserManager with the new ‘PasswordValidator’ class

Code Snippet
  1. public ApplicationUserManager(UserStore<ApplicationUser> userStore)
  2.             : base(userStore)
  3.         {
  4.         }
  5.         public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
  6.         {
  7.             var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
  8.             manager.PasswordValidator = new PasswordValidator
  9.             {
  10.                 RequiredLength = 10,
  11.                 RequireNonLetterOrDigit = true,
  12.                 RequireDigit = true,
  13.                 RequireLowercase = false,
  14.                 RequireUppercase = false,
  15.             };
  16.             return manager;
  17.         }

Here the PasswordValidator class is configured to verify that the supplied password has a non-alphanumeric character and a numeric character. Also the length of password should be of 10 characters length. Similarly other properties of the UserManager can be configured to be persisted through the context lifecycle.

Summary

This post shows how to get a per-request, single instance of the UserManager and DbContext classes from the OWIN context to be used throughout the application. This will form a base for additional blog posts outlining the new features in ASP.NET Identity 2.0.0-beta1.

I hope you have found this walkthrough useful. If you have any questions around ASP.NET Identity or find issues, please feel free to open bugs on the Identity Codeplex site, https://aspnetidentity.codeplex.com/ , leave comments on this blog, or ask questions or StackOverflow (tag: aspnet-identity). I can also be reached on twitter (@suhasbjoshi).

Ref: http://blogs.msdn.com/b/webdev/archive/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity.aspx

[Dev tip] ASP.NET MVC back button with html helper method


public static MvcHtmlString BackButton(this HtmlHelper helper, string buttonName = null, string @class = "btn btn-default")
{
if (string.IsNullOrEmpty(buttonName))
{
buttonName = Hydra.Common.I18n.ResourceConstants.Button_Back;
}

var previousURI = (System.Uri)helper.ViewContext.RequestContext.HttpContext.Request.UrlReferrer;
string result = "<a href=\"{0}\" class=\"{1}\">{2}</a>".FormatWith(previousURI, @class, buttonName);

return new MvcHtmlString(result);
}

 

on view

@Html.BackButton()

[Dev Tip] FluentAutomation for automated testing of Web Applications

Last week I was exploring today’s varied choices we have for Automated Browser Testing. There’s headless WebKit “browsers” like PhantomJS and cloud powered multi-browser testing tools like BrowserStack and SauceLabs.

Selenium is kind of the gold standard and offers not only a lot of “drivers” but also a lot of language bindings with which drive a browser. Sometimes browsers update so fast there can be some version incompatibilities with Selenium, but for the most part it works great once you’ve settled in.

One option I’ve been looking at is FluentAutomation. It’s a fluent automation API that supports Selenium as well as WatiN along with all their flavors and drivers. Since Fluient supports Selenium, that means you can use the Selenium ChromeDriver, IEDriver, Remote Web Driver or even the headless PhantomJS.FluentAutomation is on GitHub, of course, as well as on NuGet.

FluentAutomation has great (and growing) documentation and has adopted and interesting fluent style for it’s API.

Now, not everyone likes a “fluent” API so it may take a while to get used to. Often you’ll be doing things over many lines when it’s really just one line, for example, this is one line:

I.Open("http://automation.apphb.com/forms")
    .Select("Motorcycles").From(".liveExample tr select:eq(0)")
    .Select(2).From(".liveExample tr select:eq(1)")
    .Enter(6).In(".liveExample td.quantity input:eq(0)")
    .Expect
        .Text("$197.72").In(".liveExample tr span:eq(1)")
        .Value(6).In(".liveExample td.quantity input:eq(0)");

Notice the method chaining as well as the use of CSS selectors.

FluentAutomation also has the cool concept of a PageObject to take your potentially brittle scripts and give them more structure. PageObjects group your actions, expectations, and assertions and let you reuse code when a page appears in multiple tests.

For example you could have a high level test (this is XUnit, but you can use whatever you want):

public class SampleTest : FluentTest {
    public SampleTest() {
        SeleniumWebDriver.Bootstrap(SeleniumWebDriver.Browser.Chrome);
    }
    [Fact]
    public void SearchForFluentAutomation() {
        new BingSearchPage(this)
            .Go()
            .Search("FluentAutomation")
            .FindResultUrl("http://fluent.stirno.com/blog/FluentAutomation-scriptcs/");
    }
}

Then you can have separate PageObjects that have your own public methods specific to that page, as well as assertions you can reuse.

public class BingSearchPage : PageObject<BingSearchPage> {
    public BingSearchPage(FluentTest test) : base(test) {
        Url = "http://bing.com/";
        At = () => I.Expect.Exists(SearchInput);
    }
    public BingSearchResultsPage Search(string searchText) {
        I.Enter(searchText).In(SearchInput);
        I.Press("{ENTER}");
        return this.Switch<BingSearchResultsPage>();
    }
    private const string SearchInput = "input[title='Enter your search term']";
}
public class BingSearchResultsPage : PageObject<BingSearchResultsPage> {
    public BingSearchResultsPage(FluentTest test) : base(test) {
        At = () => I.Expect.Exists(SearchResultsContainer);
    }
    public BingSearchResultsPage FindResultUrl(string url) {
        I.Expect.Exists(string.Format(ResultUrlLink, url));
        return this;
    }
    private const string SearchResultsContainer = "#b_results";
    private const string ResultUrlLink = "a[href='{0}']";
}

You don’t have to be all structure and OO if you don’t want. You can just as easily write scripts with FluentAutomation and head in a different direction.

FLUENTAUTOMATION ALONG WITH SCRIPTCS = AUTOMATING YOUR BROWSER WITH C# SCRIPT

I’ve usually used Python with my Selenium scripts. I like being able to just make a text file and start scripting, then run, debug, continue, all from the command line. It feels simple and lightweight. Creating a DLL and running Unit Tests in C# usually comes later, as I can move faster with a “scripting language.”

You can do that with ScriptsCS as it gives you project-less C# that effectively is C# as scripting language. Combine this with FluentAutomation and you’ve potentially got the best of both worlds.

To install, first you need the Windows apt-get open source equivalent, the oddly-named and -spelledChocolatey. Then you get ScriptCS and the packages for FluentAutomation.

  • Install Chocolatey – one line installation here
  • Run “cinst ScriptCS” from your command line to use Chocolatey to install ScriptCS
  • Now, get the ScriptCS script packages for FluentAutomation like this:
    • scriptcs -install FluentAutomation.SeleniumWebDriver
    • scriptcs -install ScriptCs.FluentAutomation

Now, as a quick test, create a folder and put a text file called start.csx in it with just these contents:

var Test = Require<F14N>()
    .Init<FluentAutomation.SeleniumWebDriver>()
    .Bootstrap("Chrome")
    .Config(settings => {
        // Easy access to FluentAutomation.Settings values
        settings.DefaultWaitUntilTimeout = TimeSpan.FromSeconds(1);
    });
 
Test.Run("Hello Google", I => {
    I.Open(http://google.com);
});

Notice how there’s no namespace, no classes, no main. It’s just a script, except it’s using C#. You can change the “Chrome” to “IE” or “Firefox” as well, to play around.

Random: I love this Selenium feature, exposed by FluentAutomation…take screenshot!

// Take Screenshot
I.TakeScreenshot("LoginScreen");

If you don’t want ScriptCS, while it can act as a REPL itself, there is also the start of a dedicated FluentAutomation REPL (read–eval–print loop). This is basically a command prompt that lets you explore you app interactively and facilitates building your scripts. You can get the Repl as a Chocolatey package as well and just “cinst FluentAutomation.Repl”

You’ve got LOTS of choices in the world of automated testing. There’s so many choices that there’s just no good excuse. Pick a library, pick a language, and start automating your web app today.

RELATED LINKS

Ref: http://www.hanselman.com/blog/NuGetPackageOfTheWeekFluentAutomationForAutomatedTestingOfWebApplications.aspx

[Dev Tip] How to display a QR code in ASP.NET and WPF

I’ve half-jokingly said that there’s never a good reason to use a QR Code. However, I’m working on an MVP (minimally viable product) for a small startup with Greg Shackles and we actually have a good reason to use one. We have a mobile device, a Web Site, and a Windows Application, and a QR Code is a pretty quick way to move data between the mobile device and the other applications without the mess of Bluetooth pairing.

As I mentioned, we display the QR code on an ASP.NET website, as well as within a Windows app that happens to be written in WPF. The iPhone app uses C# and Xamarin.

There’s a great QR Code library called “ZXing” (Zebra Crossing) with ports in Java and also in C#. The C#/.NET one, ZXing.NETis a really fantastically well put together project with assemblies available for everything from .NET 2 to 4.5, Windows RT, Unity3D, Portable libraries and more. The site is filled with demo clients as well, although we didn’t find one for ASP.NET or WPF. No matter, it’s all just generating and showing PNGs.

I pulled in ZXing.NET from the NuGet package here, just install-package ZXing.Net.

HOW TO DISPLAY A QR CODE IN ASP.NET

If you’re generating a QR code with ASP.NET MVC, you’ll have the page that the code lives on, but then you’ll need to decide if you want to make an HTTP Handler that generates the graphic, like:

<img src="/path/to/httphandlerthatmakesQRcodepng">

or, you could take a different approach like we did, and embed the code in the HTML page itself.

Greg used an HTML Helper to output the entire image tag, including the inlined image, as in:

<img src="data:image/gif;base64,iVBORw0KG..." />

Images in HTML directly as Data URIs are super fun and I think, often forgotten. If you show one to the average web dev they’ll say “oh, ya…I knew about those, but never really used it.” In fact, Data URIs have been around for a LONG time. Learn more about them at DataUrl.net.

Here’s generating a QR Code within ASP.NET MVC from an HTML Helper:

public static class HtmlHelperExtensions
{
    public static IHtmlString GenerateRelayQrCode(this HtmlHelper html, string groupName, int height = 250, int width = 250, int margin = 0)
    {
        var qrValue = "whatever data you want to put in here";
        var barcodeWriter = new BarcodeWriter
        {
            Format = BarcodeFormat.QR_CODE,
            Options = new EncodingOptions
            {
                Height = height,
                Width = width,
                Margin = margin
            }
        };
        using (var bitmap = barcodeWriter.Write(qrValue))
        using (var stream = new MemoryStream())
        {
            bitmap.Save(stream, ImageFormat.Gif);
            var img = new TagBuilder("img");
            img.MergeAttribute("alt", "your alt tag");
            img.Attributes.Add("src", String.Format("data:image/gif;base64,{0}",
                Convert.ToBase64String(stream.ToArray())));
            return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
        }
    }
}

Nice and simple. The BarcodeWriter class within ZXing.NET does the hard work. We don’t need to save our QR Code to disk, and because we’re doing it inline from our HTML page via this helper, there’s no need for a separate call to get the image. Also, the caching policy that we decide to use for the page applies to the image within, simplifying things vs. two calls.

HOW TO DISPLAY A QR CODE IN WPF

Note: This code here may be wrong. I’m happy to hear your suggestion, Dear Reader, because I’m either missing something completely or there is no clear and clean way to get from a System.Drawing.Bitmap to a System.Windows.Media.imaging.BitmapImage. The little dance here with the saving to a MemoryStream, then moving into a BitmapImage (with the unintuitive but totally required setting of CacheOption as well) just sets off my Spideysense. It can’t be right, although it works.

I’ll update the post when/if a cleaner way is found.

See below for update!

First, the exact same BarcodeWriter usage from the ZXing.NET library.

var qrcode = new QRCodeWriter();
var qrValue = "your magic here";
var barcodeWriter = new BarcodeWriter
{
    Format = BarcodeFormat.QR_CODE,
    Options = new EncodingOptions
    {
        Height = 300,
        Width = 300,
        Margin = 1
    }
};
using (var bitmap = barcodeWriter.Write(qrValue))
using (var stream = new MemoryStream())
{
    bitmap.Save(stream, ImageFormat.Png);
    BitmapImage bi = new BitmapImage();
      bi.BeginInit();
        stream.Seek(0, SeekOrigin.Begin);
        bi.StreamSource = stream;
        bi.CacheOption = BitmapCacheOption.OnLoad;
      bi.EndInit();
      QRCode.Source = bi; //A WPF Image control
}

Later, writing the Bitmap to a MemoryStream for manipulation, except in this case, we’re putting the QR Code into the Source property of a WPF Image Control.

UPDATE: Thomas Levesque in the comments below suggests an extension within System.Windows.Interop (which explains me not finding it) called CreateBitmapSourceFromHBitmap. This still feels gross as it appears to requires a call to the native DeleteObject, but regardless, that’s the price you pay I guess. It looks like this:

using (var bitmap = barcodeWriter.Write(qrValue))
{
    var hbmp = bitmap.GetHbitmap();
    try
    {
        var source = Imaging.CreateBitmapSourceFromHBitmap(hbmp, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        QRCode.Source = source;
    }
    finally
    {
        DeleteObject(hbmp);
    }
}

It works well!

Ref: http://www.hanselman.com/blog/CategoryView.aspx?category=NuGetPOW

[Startup] Founder của mWork và Appota bật mí về hệ sinh thái startup làm di động (Video)

hanoi-meetup-tech-in-asia-720x540 copyHồi tháng Tư, Tech In Asia đã tổ chức Hội thảo đầu tiên tại Hà Nội. Trong buổi này, chúng tôi đã có cơ hội chào đón hơn 200 khách tham dự với phần trình bày của anh Dũng Trần, người sáng lập mWork, và anh Đỗ Tuấn Anh, người sáng lập Appota, về kinh nghiệm khởi nghiệp thành công trên di động. Hai anh cũng đưa ra lời khuyên cho các startup đang “máu lửa” với lĩnh vực này.

 

(Xin xem phiên bản tiếng Anh của bài viết tại đây)

 

Điểm nhấn hàng đầu trong buổi phỏng vấn chính là sự chân thực và vô cùng hài hước của hai vị khách mời. Họ là bạn bè lâu năm và họ đã trêu đùa nhau trong suốt buổi phỏng vấn. Đi từ chiếc xe hơi của anh Tuấn Anh sang đến bộ râu của anh Dũng, cả hai thậm chí chỉ trích nhau trong khi vẫn rất thân thiết và chia sẻ thực về những điểm mà một người đứng đầu startup cần có tại Việt Nam. Toàn bộ cuộc phỏng vấn bằng tiếng Việt nhưng chúng tôi đã biên dịch sang phụ đề tiếng Anh cho khán giả quốc tế.

(Chúng tôi cũng sắp tổ chức một buổi hội thảo khác tại TP. HCM với các khách mời tên tuổi như Esther Nguyễn đến từ POPS Việt Nam và blogger nổi tiếng Toàn Shinoda)

Bạn sẽ cảm nhận rõ hơn sự vui nhộn của buổi nói chuyện nếu bạn biết rằng những nhân vật mà trước đây hai vị khách mời đã làm việc cho họ, cũng có mặt ở đó (một số còn đặt câu hỏi vào cuối buổi), làm cho không khí buổi nói chuyện càng chân thực và gần gũi. Vì vậy, chúng tôi khuyên bạn nên xem từ đầu đến cuối các video. Nhưng đối với những ai không có thời gian, chúng tôi tóm gọn những điểm chính của buổi nói chuyện lại như bên dưới:

  • Apota đã nhận đầu tư hồi đầu năm 2012 và đến cuối năm đó đã tiêu hết tiền.
  • Dũng đã thất bại nhiều lần trước khi làm mWork. Anh thậm chí còn thất bại khi mở một công ty truyền thông, và quay lại làm việc cho FPT.
  • Dũng nói rằng thị trường game di động Việt Nam hiện đang có giá trị một tỷ đô.
  • Dũng nói rằng thương mại điện tử sẽ trở thành làn sóng lớn tiếp theo trên thiết bị di động.
  • Tuấn Anh nói rằng đích đến lớn nhất của Appota là đóng góp nhiều hơn nữa cho hệ sinh thái khởi nghiệp ở Việt Nam.
  • Dũng nói sau năm 2015, thị trường sẽ ổn định hơn và khi đó khó lòng mà các startup mới bước vào thị trường, nếu không thực sự đột phá.
  • Dũng tin rằng có ba yếu tố chính dẫn đến thành công: chọn đúng ngành nghề, chọn đúng mô hình, và tuyển dụng được một đội ngũ nhân sự tốt.
  • Tuấn Anh tin rằng chìa khoá thành công chính là biết cách kết hợp hài hòa những gì chúng ta yêu thích và những gì thị trường cần.

Bạn có thể theo dõi toàn bộ buổi phỏng vấn bên dưới:

Cuối cùng, chúng tôi muốn gửi lời cảm ơn đến những người bạn của chúng tôi là Hatch, Topica, VTC, và Aiti Education, các bạn đã giúp quảng bá sự kiện này cho hệ sinh thái khởi nghiệp đang lớn mạnh của Hà Nội. Chúng tôi cũng muốn gửi lời cảm ơn chân thành đến Techcrunch đã tài trợ cho buổi tiệc thân mật sau sự kiện.

hanoi-meetup-techcrunch-tech-in-asia-hanoi-720x540

Biên tập bởi Jeffrey Quigley

Biên dịch bởi Quyen Quyen

[Infographic] Bức tranh ” khổng lồ” về thị trường bán lẻ Việt Nam

Mặc dù nền kinh tế chưa khởi sắc nhưng thị trường bán lẻ Việt Nam vẫn là một lĩnh vực rất sôi động. Do đặc thù cơ sở hạ tầng và giao thông Việt Nam, mô hình siêu thị trung bình từ 2.500 đến 3.000 mét vuông sẽ trở nên phổ biến. Bên cạnh đó, thương mại điện tử sẽ có tương lai tươi sáng nếu khắc phục được điểm yếu kém của mình về chuỗi cung ứng và hậu cần.

Đặc biệt theo thống kê thì có 3 thương hiệu thuần túy hoạt động TMĐT là Lazada, Nhóm mua, Mua chung vào top đơn vị bán lẻ được biết đến nhiều nhất.

Điểm thử thách lớn nhất cho bất cứ hệ thống bán lẻ nào hiện nay là sự thiếu hụt nhân sự được đào tạo chuyên nghiệp.

Sau đây là những con số về thị trường bán lẻ “khổng lồ” của Vệt Nam:

7c050231170344355901ed6a0e971f846151c8261366081379

 

[Startup] Lắng nghe nhà đầu tư: Những yếu tố nào của startup được nhà đầu tư chú trọng nhất?

Trong khi thực trạng startup tại Việt Nam cho đến nay vẫn chưa có gì thực sự khởi sắc thì chúng ta có thể nhận thấy nguồn tiền đầu tư từ các quỹ đầu tư mạo hiểm nước ngoài chảy vào Việt Nam vẫn rất lớn.

Quỹ đầu tư mạo hiểm lớn nhất tại Việt Nam hiện nay có lẽ phải kể đến IDG Ventures với danh sách đầu tư đã lên đến 43 công ty với những cái tên đình đám như VCCorp, Vatgia, Peacesoft,… Bên cạnh đó, với giới đầu tư mạo hiểm chắc chắn sẽ là một thiếu sót nếu không kể đến cái tên CyberAgent Ventures với danh sách đầu tư tại Việt Nam là 12 công ty và những cái tên nổi bật trong danh sách này bao gồm VNG, Tiki.vn và CleverAds.

Anh Nguyễn Mạnh Dũng -  Giám đốc CyberAgent Ventures tại Việt Nam và Thái Lan

Chúng tôi đã có cuộc nói chuyện với anh Nguyễn Mạnh Dũng – Giám đốc CyberAgent Ventures tại Việt Nam và Thái Lan về những yếu tố mà nhà đầu tư mạo hiểm chú trọng xem xét nhát trươc khi ra quyết định đầu tư vào startup công nghệ tại Việt Nam. Anh Dũng được biết đến nhiều trong cộng đồng với cái tên Dzung Nguyen.

Các nhà đầu tư chú trọng những yếu tố gì trước khi quyết định đầu tư?

Đội ngũ startup

Để trả lời cho câu hỏi này, anh Dũng chia sẻ khi bắt đầu tìm kiếm startup về công nghệ để đầu tư tại Việt Nam, việc đầu tiên cần bắt đầu là với đội ngũ của startup đấy.

Startup không chỉ có mục tiêu ngắn hạn trước mắt mà còn phải có cái nhìn chiến lược lâu dài. Họ phải nhìn ra xa vượt qua tình trạng hiện tại và cần phải có đam mê về việc gây dựng nên sự nghiệp của mình. Và xuất phát điểm khởi nghiệp của họ không nên chỉ vì tiền, mà nên bắt đầu bằng việc mang lại nhiều lợi ích hơn cho người dùng hoặc để hỗ trợ phát triển điều gì đó. Một đội ngũ startup nên được bắt đầu bằng những người có tầm nhìn như vậy.

Nhưng chỉ sống bằng đam mê thì không được mà startup cần phải tự hiểu rõ về bản thân mình. Startup cần phải làm rõ được họ cần gì từ nhà đầu tư và họ sẽ làm gì với khoản tiền được nhận và sẽ làm thế nào để sinh lời. Anh Dũng cho biết:

Khi bắt đầu sự nghiệp, điều đầu tiên bạn cần làm đó là tìm ra điểm mạnh của mình là gì. Nếu ngay chính bạn còn không tìm được điều đó thì làm sao những nhà đầu tư có thể hiểu được? Chúng tôi, với tư cách là những nhà đầu tư cần phải biết được điểm mạnh và điểm yếu của bạn để tìm ra được giải pháp hỗ trợ các bạn tốt nhất. Một đội ngũ tốt cần phải biết được vị trí của mình đang ở đâu và họ nên làm gì tiếp theo. Nếu chưa tìm ra được điều này, có lẽ trước tiên họ cần tìm đến một người chỉ dẫn (mentor). Nhưng một yếu tố tiên quyết startup cần biết trước khi tìm đến nhà đầu tư là họ cần gì?

Mục tiêu rõ ràng

Tuy nhiên, đội ngũ tốt không thể giải quyết được toàn bộ vấn đề, vì không thể nào có chuyện chỉ một đội tốt có thể cứu vãn được ý tưởng hay sản phẩm tồi. Sẽ không có một nhà đầu tư nào điên rồ đến mức lãng phí tiền bạc, mối quan hệ và những nguồn lực của mình để hỗ trợ cho một sản phẩm chẳng rõ ràng về mục đích sử dụng.

Điểm trừ lớn nhất khi startup đến gặp nhà đầu tư đó chính là thậm chí không biết được vấn đề mà sản phẩm của mình đang giải quyết là gì. Cần phải trả lời được những câu hỏi sau: “Sản phẩm của mình sẽ giải quyết được vấn đề nào của người dùng?” Nếu bạn không có được mục đích sử dụng rõ ràng cho sản phẩm của mình thì làm sao có thể thu hút người dùng về cho mình?

Điều tôi mong có thể nghe được từ những startup đó chính là “Chúng tôi biết người dùng đang gặp vấn đề này và đang rất cần giải pháp mà chúng tôi đưa ra. Bằng cách tối ưu hóa những kĩ năng công nghệ mà chúng tôi có được, chúng tôi sẽ đem đến giải pháp cho vấn đề đó.”

Quy mô và tiềm năng của thị trường

HCMC_Skyline

Quy mô thị trường cũng là vấn đề lớn cần quan tâm. Anh Dũng nhấn mạnh:

Ngay cả khi startup của bạn có một đội ngũ vững mạnh, nhưng bạn lại nhắm đến thị trường quá nhỏ thì kết quả bạn thu được vẫn chẳng thấm vào đâu. Bởi ngay cả khi bạn nắm được toàn bộ thị trường thì quy mô doanh nghiệp của bạn cũng không thể lớn hơn được. Vì vậy chúng tôi quan tâm về quy mô thị trường và cách bạn có thể làm cho startup của mình lớn mạnh và sinh lời”

Nhà đầu tư có quan tâm đến mô hình kiếm tiền của startup?

Rất nhiều startup hiện nay “ngây thơ” chỉ chăm chú vào việc làm sao có được lượng người dùng lớn nhất thay vì tìm ra được mô hình kiếm tiền. Nhưng cần phải nhớ rằng nếu bạn chưa tìm ra được mô hình kiếm tiền rõ ràng cho startup của mình, bạn sẽ không thu hút được nhà đầu tư.

Anh Dũng nhấn mạnh rằng đối với startup, có thể tiền không phải là vấn đề quan trọng nhất trong 3 năm đầu tiên nếu nhận được đầu tư. Tuy nhiên, startup cần phải chủ động tìm ra cách tự sống sót được tiếp mà không cần tiền từ nhà đầu tư.

Nếu như startup tin tưởng rằng sản phẩm/dịch vụ của mình có thể thực sự mang lại lợi ích cho người dùng nhưng họ cần thời gian. Vậy bao nhiêu thời gian mới là đủ, và cái quan trọng hơn tiền đâu ra để họ có thể tồn tại đến lúc hái quả? Startup có thể sống dựa vào tiền đầu tư trong 3 năm đầu nhưng nếu không tự tìm ra được mô hình kiếm tiền cho mình vậy thì họ sẽ tính thế nào với năm thứ 4 trở đi? Làm thế nào để tiếp tục startup của mình mà không có nhà đầu tư? Nếu họ không tìm ra được thì startup sẽ chết.

Bên cạnh đó, anh Dũng đưa ra một so sánh khi ở Mỹ, nếu bạn có lượng người dùng lớn thì khả năng nhận được đầu tư là rất lớn. Tuy nhiên, điều này lại hoàn toàn khác ở Đông Nam Á – nơi các khoản đầu tư ở giai đoạn series A là khá phổ biến, thì một thực tế là chi càng nhiều tiền thì sẽ càng nhanh có lượng người dùng lớn. Nhưng sau đó thì sao? Vì vậy, đối với Đông Nam Á mà đặc biệt là Việt Nam, cái nhà đầu tư nhìn vào không chỉ dừng ở lượng người dùng mà chắc chắn phải nhìn xa hơn về phương thức kiếm tiền và mục đích sử dụng của sản phẩm/ dịch vụ mà startup mang lại.

(Biên tập bởi Sơn Trần)

[Life] 10 câu nói giúp bạn hiểu hơn về truyền thông xã hội

Enterprise-Social-Networking-SuccessNgày nay truyền thông xã hội đã trở thành một xu thế toàn cầu. Với sự hỗ trợ của mạng xã hội, của những trang web chia sẻ bài viết, hình ảnh, và video, đã đưa truyền thông xã hội trở thành một chiến lược marketing phải có đối với các doanh nghiệp, đặc biệt là với các startup non trẻ.

Tuy nhiên, để có thể sử dụng truyền thông xã hội một cách hiệu quả, chúng ta cần phải tìm hiểu về nó, cả về những điểm tích cực cũng như tiêu cực nhằm khai thác tối đa tiềm năng cũng như giúp chúng ta tránh đi những sai lầm không cần thiết.

Dưới đây là 10 phát biểu tâm huyết của những chuyên gia đã hoạt động lâu năm trong lĩnh vực truyền thông xã hội, giúp các bạn có cái nhìn nhiều chiều hơn về bản chất, cách vận hành cũng như những hiệu quả truyền thông xã hội có thể đem lại.

1- “Bạn là chính những gì bạn chia sẻ”.

(Trong cuốn We Think: The power of mass creaativity của Charles Leadbeater – Nhà văn người Anh, cố vấn của Thủ tướng Tony Blair)

2- “Truyền thông xã hội đầu độc thế giới bởi một loại virus ghê gớm tên là “sự phù phiếm””.

(Kellie Elmore – Nhà văn, blogger người Mỹ)

3- “Truyền thông xã hội là cơ hội để bạn có một lượng lớn người dùng trung thực, trung thành và minh bạch”.

(Trích trong cuốn Social Media for the Executive của Brian E. Boyd Sr – Nhà văn người Mỹ, CEO Media Connect)

4- “Tôi càng sôi nổi và hay tranh luận thì càng có nhiều người theo dõi và kết bạn online với tôi”.

(Tasha Turner– Nhà văn Mỹ, người hướng dẫn truyền thông xã hội)

5- “Ngày nay, một kẻ khờ cũng có thể làm được một trang web”.

(Trích trong cuốn Blood Bound của Patricia Briggs– Nhà văn, phóng viên của New York Times)

6- “Nếu bạn muốn tạo ra cái mới thì hãy dừng cách làm cũ”.

(Peter F. Drucker Nhà văn, Giáo sư người Mỹ).

7- “Sự thật vĩ đại nhất của thời đại này: Thông tin không phải là tri thức”.

(Caleb CarrNhà văn, nhà sử học quân sự người Mỹ).

8- “Đừng chỉ sưu tập các fan hâm mộ, hãy tác động đến họ”.

(Jay Baer – Founder của Convinceandconvert, diễn giả người Mỹ)

9- “Tham gia vào LinkedIn là cách tốt nhất để nói “Hãy nhìn vào tôi” mà không cần phải nói “Hãy nhìn vào tôi”

(Bobby Darnell – Founder của Construction Market Consulations)

10- “Những người kỳ quặc thường nổi bật”.

(Dan SchawbelPhóng viên, nhà bình luận của Forbes, New York Times).

(Chúng tôi sẽ có một buổi gặp gỡ các tên tuổi trong làng giải trí online như POPS, Blogger Toàn Shinoda, Hưng Zino và sẽ chia sẻ nhiều hơn về các bí quyết làm truyền thông xã hội. Xin đăng ký tham dự sự kiện tại đây)

(Biên tập bởi Quyen Quyen)