非同期コントローラ使ってみた - まめしば雑記
http://d.hatena.ne.jp/shiba-yan/20100715/1279204349

上記のブログで非同期コントローラーが面白そうだったので、前回の ASP.NET MVC で複数ファイルのアップロード を少し修正して試してみました(※ASPX部分は そのまま使用しています)。

基本的には、基本クラス(Controller → AsyncController) とアクション名(Index → IndexAsync) を変えて、完了時のメゾット(IndexCompleted) を定義しているだけですが、アップロードされたファイルをそのまま保存しては、非同期にする意味がほとんどないので、保存後にメールでファイルを送る処理を追加しています。

    [HandleError]
    public class HomeController : AsyncController
    {
        [HttpPost]
        public ActionResult IndexAsync(HttpPostedFileBase[] fileUpload)
        {
            foreach (var f in fileUpload)
            {
                AsyncManager.OutstandingOperations.Increment();
                Thread t = new Thread(new ParameterizedThreadStart(Upload));
                t.Start(f);
            }
            return View();
        }

        private void Upload(object o)
        {
            HttpPostedFileBase f = (HttpPostedFileBase)o;
            if (f != null)
            {
                string filePath = Path.Combine(
                    HttpContext.Server.MapPath("~/App_Data/Uploaded/"),
                    Path.GetFileName(f.FileName));
                f.SaveAs(filePath);
				
                MyMail.Send(filePath);
            }
            AsyncManager.OutstandingOperations.Decrement();
        }

        public ActionResult IndexCompleted()
        {
            ViewData["msg"] = "アップロードが完了しました。";
            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }

 

メールを送ってる部分は、こんな感じです。

    public class MyMail
    {
        public static void Send(string fineName)
        {
            string from = "差出人メールアドレス";
            string to = "送信先メールアドレス";
            using (System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(from, to))
            {
                //添付ファイル
                System.Net.Mail.Attachment attachment;
                attachment = new System.Net.Mail.Attachment(fineName);
                attachment.ContentType = new System.Net.Mime.ContentType("image/jpeg");
                msg.Attachments.Add(attachment);

                System.Net.Mail.SmtpClient sc = new System.Net.Mail.SmtpClient();
                sc.Host = "メールサーバ";

                sc.Send(msg);
            }
        }
    }

 

参考

非同期コントローラ使ってみた - まめしば雑記
http://d.hatena.ne.jp/shiba-yan/20100715/1279204349

ASP.NET MVC での非同期コントローラーの使用 - MSDN
http://msdn.microsoft.com/ja-jp/library/ee728598.aspx

環境:.NET Framework 4, ASP.NET MVC 2

ASP.NET MVC で複数のファイルをアップロードしてみます。

ファイルのアップロードが可能なフォームを作成して、ファイルを複数(今回は5つ)アップロードできるようにタグを記述します。

    <% using (Html.BeginForm("Index", "Home",
           FormMethod.Post, new { enctype = "multipart/form-data" }))
       { %>
    <p><input id="fileUpload1"  name="fileUpload" type="file" /></p>
    <p><input id="fileUpload2"  name="fileUpload" type="file" /></p>
    <p><input id="fileUpload3"  name="fileUpload" type="file" /></p>
    <p><input id="fileUpload4"  name="fileUpload" type="file" /></p>
    <p><input id="fileUpload5"  name="fileUpload" type="file" /></p>
    <p> <input type="submit" value="送信" /></p>
    <p><%: ViewData["msg"]%></p>
    <% } %>

 

こんな感じのページになります。

img1

 

コード部分はHttpPostedFileBaseクラスから、アップロードされたファイルを取得し保存するだけで完了です。

    public class HomeController : Controller
    {
        [HttpPost]
        public ActionResult Index(HttpPostedFileBase[] fileUpload)
        {
            foreach (var f in fileUpload)
            {
                if (f != null)
                {
                    string filePath = Path.Combine(
                        HttpContext.Server.MapPath("~/App_Data/Uploaded/"),
                        Path.GetFileName(f.FileName));
                    f.SaveAs(filePath);
                }
            }

            ViewData["msg"] = "アップロードが完了しました。";
            return View();
        }

    }

VS2008 の ASP.NET MVC 1 を ASP.NET MVC 2 に移行したときのメモです。

 

VS2008のASP.NET MVC 2へ移行

VS2008で作ったASP.NET MVC 1 を  VS2008 の ASP.NET MVC 2 に移行する場合は、下記ページにあります Converter を使用します。

Migrating ASP.NET MVC 1.0 applications to ASP.NET MVC 2 RTM

使い方は簡単で、

1.ダウンロードしたファイルを展開し起動
2.「Browse...」をクリックしてASP.NET MVC 1のソリューションファイルを指定
3.「Convert」ボタンをクリック

するだけです。

※VS2008 で 変換したソリューションファイルを開くには ASP.NET MVC 2 のインストールが必要です。

ASP.NET MVC 2 RTM - AspNetMVC2_VS2008.exe

 

 VS2010のASP.NET MVC 2へ移行

VS2010の場合は、ウィザードで自動的に変換します。

VS2010を起動して、VS2008で作ったASP.NET MVC 1 のソリューション(プロジェクト)ファイルを開けば、「Visual Studio 変換ウィザード」が起動しますので、そのまま自動的にASP.NET MVC 1 から ASP.NET MVC 2 に移行できます。

 

その他

ASP.NET MVC 2では、ヘルパーが stringから MvcHtmlString を返すよう変更されているので、replece 使ったり、三項演算子(条件演算子「? :」)を使ってる部分などは修正が必要です。

また、サーバーに ASP.NET MVC 2 をインストールされていない環境でも、参照設定にある下記のローカルコピーをTrueに設定し、サーバーにコピーするように設定すれば動きます。

System.Web.Mvc
System.Web.Routing
System.Web.Abstractions

ASP.NET MVC では、サーバーサイドとクライアントサイドのバリデーションを1カ所にまとめる方法として、xVal を使ってバリデーションする方法を紹介しましたが、ASP.NET MVC 2 では下記3行追加するだけで、クライアントサイドでもバリデーションが行われます。

    <script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
    <% Html.EnableClientValidation(); %>

キャプチャーでは動きがわからないですが、こんな感じになります。

20100621

環境: PowerShell v2 (Windows 7)  ※サーバー側は、IIS7.5, ASP.NET MVC

PowerShellでWebClientのUploadFileメゾットを使用しWebサイトへファイルをアップロードします。

$wc = New-Object Net.WebClient 
$wc.Credentials = $wc.Credentials = [Net.CredentialCache]::DefaultCredentials

try {
	$res = $wc.UploadFile("http://www.gine.jp/home/Upload2", "c:\Temp\Koala.jpg")
    $s = [text.encoding]::UTF8.getString($res)
    Write-Output $s
} 
catch [Exception] 
{
    Write-Output $_.Exception.Message
}
finally
{
    $wc.Dispose()
}

 

ちなみに受信する側は ASP.NET MVC で新規プロジェクトを作成し、HomeController.cs に下記コードを追加してあります。

HomeController.cs

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Upload(HttpPostedFileBase file)
{
	string fn = @"c:\temp\upload\" + System.IO.Path.GetFileName(file.FileName);
	file.SaveAs(fn);

	return Content("アップロード完了", "text/plain");
}

 

保存が完了したら、"アップロード完了"というテキストを返しています。

また、PowerShell で WebClientのUploadFileメゾットでアップロードを行っていますのでHttpPostedFileBase は "file"となります。