ラベル ASP.NET MVC の投稿を表示しています。 すべての投稿を表示
ラベル ASP.NET MVC の投稿を表示しています。 すべての投稿を表示

2021年4月5日月曜日

Visual Studio 2017 2019 ASP.NET MVC で AREA を追加する方法

プロジェクトを右クリック→「追加」→「新規スキャフォールディングアイテム」


「共通」→「MVC」→「区分」

以上、メモまで。

2020年6月4日木曜日

AdminLTE3 を ASP.NET Core へ

AdminLTE.cssはbootstrap4を含んでいるので重複してローディングしてはいけない。 https://adminlte.io/docs/3.0/upgrade-guide.html 以上、メモまで。

2018年7月23日月曜日

PDFSharp MigraDoc を使ってC#でPDF生成

(正確を期するよう努力いたしておりますが、保証するものではありません。予めご了承願います。)

帳票のような物をPDF出力する必要があり、iTextSharpを久しぶりに利用しようとしたところライセンスがさらに厳しくなっており、代わりとしてPDFSharp(MITライセンス)を利用することにしました。


こちらのページから概要や特徴、ソースのダウンロードページやwiki、forumへアクセスすることができます。

概要

1.PDFSharp と MigraDoc

PDFSharp
- PDFファイルを操作するための.NETライブラリ。テキストはもちろん線や画像の描画もできる。テーブル組や自動改ページなどはない。
MigraDoc
- PDFSharpを使用してよりドキュメント作成に便利な高機能を提供するライブラリ。テーブル組や自動改ページに対応。
Mix
- MigraDocはPDFSharpで構築されているので、両者を混合して利用する事もできる。
MigraDoc Sample: Mix MigraDoc and PDFsharp - PDFsharp and MigraDoc Wiki

2.Github


ソースコードはこちらから入手できます。
samples が便利なので詰まった時は参考にされると解決するかもしれません。

準備

PDFSharp,MigraDocどちらもVisual Studio の Nuget Package でインストールできます。
上図の通り、いくつか種類があってどれをインストールすれば良いか悩みます。
それぞれの使い分けは以下の通りです。
PDF Core Build 未完成。完成すればプラットフォームに依存せずMacやLinuxでも動作する予定。
GDI+ Build .NET 2.0、C# 2 で作成。WinForms、 Web アプリケーションで動作。( WPF でも動作する)
WPF Build .NET 3.5、C# 2 で作成。その名の通り WPF アプリケーションで動作。
Hybrid Build GDI+ WPF をひとつのプロジェクトで共存。ただし、動作が重くなるなど問題があり実際のアプリケーションで利用するのは非推奨。
Supported Platforms and Technologies, Available Builds - PDFsharp and MigraDoc Wiki

サンプル

ASP.NET MVC で日本語フォントを含むPDFを出力するサンプルを作成します。
MigraDoc GDI+ を Nuget でインストールします。

日本語フォントを利用するためにはIFontResolverを継承したクラスを作成し、それをプログラムに登録する必要があります。
以下のサイトを参考にさせていただきました。

生成結果のPDFは以下の通りです。サンプルデータを作成するのにWikipediaの内容を一部利用しております。(https://ja.wikipedia.org/wiki/FIFAワールドカップ)
色付きの部分は追記した補足説明(英文字はコード内で自分が命名した変数など)で、プログラムで生成したものではありません。
(ヘッダやパラグラフにわかりやすくなるように枠線をつけています。)

Documentクラスに表紙や目次、第何章などのSection(章)を追加し、その章の中にParagraph(段落)やTable(表組み)などを追加していって文書を作成していきます。
このサンプルを作成するのに記述したコードは以下の通りです。

using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using System.IO;
using System.Web.Mvc;

namespace MigraDocSample.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // フォントリゾルバーのグローバル登録
            PdfSharp.Fonts.GlobalFontSettings.FontResolver = new JapaneseFontResolver();

            //ドキュメント作成
            Document document = new Document();
            document.Info.Title = "Hello, MigraDoc";
            document.Info.Subject = "This is MigraDoc Sample.";
            document.Info.Author = "Author";
            document.DefaultPageSetup.LeftMargin = Unit.FromCentimeter(2);
            document.DefaultPageSetup.RightMargin = Unit.FromCentimeter(2);
            document.DefaultPageSetup.TopMargin = Unit.FromCentimeter(10);
            document.DefaultPageSetup.BottomMargin = Unit.FromCentimeter(5.5);
            
            //表紙セクション作成
            Section sectionCover = document.AddSection(); //Sectionを追加

            Font fontCoverTitle = new Font("yumin",30); //登録したフォント
            fontCoverTitle.Underline = Underline.Single;
            Paragraph paragraphCover = sectionCover.AddParagraph(); //Paragraphを追加
            paragraphCover.AddFormattedText("表紙タイトル",fontCoverTitle);
            paragraphCover.Format.SpaceBefore = "3cm";
            paragraphCover.Format.SpaceAfter = "3cm";
            paragraphCover.Format.Alignment = ParagraphAlignment.Center;

            Font fontDate = new Font("yumin", 8);
            Paragraph paragraphDate = sectionCover.AddParagraph();
            paragraphDate = sectionCover.AddParagraph();
            paragraphDate.AddFormattedText("Rendering date: ", fontDate);
            paragraphDate.AddDateField();
            paragraphDate.Format.Alignment = ParagraphAlignment.Right;

            //メインセクション作成
            Section sectionMain = document.AddSection();
            sectionMain.PageSetup.HeaderDistance = Unit.FromCentimeter(2);
            sectionMain.PageSetup.FooterDistance = Unit.FromCentimeter(1.5);
            sectionMain.PageSetup.StartingNumber = 1;

            //ヘッダテーブル作成
            Table tableHeader = new Table();
            tableHeader.Borders.Visible = true;
            tableHeader.TopPadding = 0;
            tableHeader.BottomPadding = 5;

            //3列作成
            var columnHeader = tableHeader.AddColumn(Unit.FromCentimeter(6));
            columnHeader.Format.Alignment = ParagraphAlignment.Left;
            columnHeader = tableHeader.AddColumn(Unit.FromCentimeter(3));
            columnHeader.Format.Alignment = ParagraphAlignment.Right;
            columnHeader = tableHeader.AddColumn(Unit.FromCentimeter(8));
            columnHeader.Format.Alignment = ParagraphAlignment.Left;

            var fontHeaderTitle = new Font("yumin", 18);
            fontHeaderTitle.Underline = Underline.Single;
            var fontHeader = new Font("yumin", 10);
            var para = new Paragraph();

            //1行目
            para.AddFormattedText("FIFAワールドカップ", fontHeaderTitle);
            var row = tableHeader.AddRow();
            row.Height = 30;
            row.Cells[0].Add(para);
            row.Cells[0].MergeRight = 2;
            row.Cells[0].Format.Alignment = ParagraphAlignment.Center;
            //2行目
            row = tableHeader.AddRow();
            para = row.Cells[1].AddParagraph();
            para.AddFormattedText("開始年", fontHeader);
            para = row.Cells[2].AddParagraph();
            para.AddFormattedText("1930年", fontHeader);
            //3行目
            row = tableHeader.AddRow();
            para = row.Cells[1].AddParagraph();
            para.AddFormattedText("主催", fontHeader);
            para = row.Cells[2].AddParagraph();
            para.AddFormattedText("FIFA", fontHeader);
            //4行目
            row = tableHeader.AddRow();
            para = row.Cells[1].AddParagraph();
            para.AddFormattedText("地域", fontHeader);
            para = row.Cells[2].AddParagraph();
            para.AddFormattedText("世界", fontHeader);
            //5行目
            row = tableHeader.AddRow();
            para = row.Cells[1].AddParagraph();
            para.AddFormattedText("参加チーム数", fontHeader);
            para = row.Cells[2].AddParagraph();
            para.AddFormattedText("32(本大会)", fontHeader);
            //6行目
            row = tableHeader.AddRow();
            para = row.Cells[1].AddParagraph();
            para.AddFormattedText("出典", fontHeader);
            para = row.Cells[2].AddParagraph();
            para.AddFormattedText("https://ja.wikipedia.org/wiki/FIFAワールドカップ", fontHeader);

            sectionMain.Headers.Primary.Add(tableHeader); //sectionにヘッダーを追加

            //本文作成
            var fontMainTitle = new Font("yumin", 14);
            fontMainTitle.Underline = Underline.Dash;
            var fontMain = new Font("yumin", 10);
            //1段落目(英文は英文のルールに従って改行される)
            var paraMain = document.LastSection.AddParagraph();
            paraMain.Format.Borders.Visible = true;
            paraMain.Format.RightIndent = Unit.FromCentimeter(5);
            paraMain.AddFormattedText("English\n",fontMainTitle);
            paraMain.AddLineBreak();
            paraMain.Format.Font = fontMain;
            paraMain.AddText(Sample.English);
            paraMain.AddLineBreak();
            //2段落目(日本語文は改行されずに)
            paraMain = document.LastSection.AddParagraph();
            paraMain.Format.Borders.Visible = true;
            paraMain.Format.RightIndent = Unit.FromCentimeter(5);
            paraMain.AddFormattedText("日本語コンテンツ\n", fontMainTitle);
            paraMain.AddLineBreak();
            paraMain.Format.Font = fontMain.Clone();
            paraMain.AddText(Sample.Japanese);
            paraMain.AddLineBreak();
            //3段落目
            paraMain = document.LastSection.AddParagraph();
            paraMain.Format.Borders.Visible = true;
            paraMain.Format.RightIndent = Unit.FromCentimeter(5);
            paraMain.AddFormattedText("日本語コンテンツ(1文字ずつ)\n", fontMainTitle);
            paraMain.AddLineBreak();
            paraMain.Format.Font = fontMain.Clone();
            foreach (char c in Sample.Japanese)
            {
                paraMain.AddFormattedText(c.ToString(), fontMain);
            }
            paraMain.AddLineBreak();

            document.LastSection.AddPageBreak(); //改ページ

            //テーブル表記
            paraMain = document.LastSection.AddParagraph();
            paraMain.AddFormattedText("歴代大会結果", fontMainTitle);
            Table tableResult = new Table();
            tableResult.Borders.Visible = true;
            tableResult.Rows.Height = 25;
            //7列作成
            var columnResult = tableResult.AddColumn(Unit.FromCentimeter(0.8));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(1.8));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(3.1));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(0.5));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(3.1));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(3.8));
            columnResult = tableResult.AddColumn(Unit.FromCentimeter(3.1));
            //ヘッダ1行目
            row = tableResult.AddRow();
            para = row.Cells[0].AddParagraph(); para.AddFormattedText("回", fontMain);
            para = row.Cells[1].AddParagraph(); para.AddFormattedText("開催年", fontMain);
            para = row.Cells[2].AddParagraph(); para.AddFormattedText("開催国", fontMain);
            para = row.Cells[3].AddParagraph();
            para = row.Cells[4].AddParagraph(); para.AddFormattedText("決勝戦", fontMain);
            row.Cells[4].MergeRight = 2;
            row.Cells[0].MergeDown = 1;
            row.Cells[1].MergeDown = 1;
            row.Cells[2].MergeDown = 1;
            row.Cells[3].MergeDown = 1;
            //ヘッダ2行目
            row = tableResult.AddRow();
            para = row.Cells[4].AddParagraph(); para.AddFormattedText("優勝", fontMain);
            para = row.Cells[5].AddParagraph(); para.AddFormattedText("結果", fontMain);
            para = row.Cells[6].AddParagraph(); para.AddFormattedText("準優勝", fontMain);
            foreach (var result in Sample.Results)
            {
                row = tableResult.AddRow();
                if (result.Organized)
                {
                    para = row.Cells[0].AddParagraph(); para.AddFormattedText(result.Number.ToString(), fontMain);
                    para = row.Cells[1].AddParagraph(); para.AddFormattedText(result.Year.ToString() + "年", fontMain);
                    para = row.Cells[2].AddParagraph(); para.AddFormattedText(result.Host, fontMain);
                    para = row.Cells[3].AddParagraph();
                    para = row.Cells[4].AddParagraph(); para.AddFormattedText(result.Champion, fontMain);
                    para = row.Cells[5].AddParagraph(); para.AddFormattedText(result.FinalScore, fontMain);
                    para = row.Cells[6].AddParagraph(); para.AddFormattedText(result.RunnersUp, fontMain);
                }
                else
                {
                    para = row.Cells[1].AddParagraph(); para.AddFormattedText(result.Year.ToString() + "年", fontMain);
                    para = row.Cells[4].AddParagraph(); para.AddFormattedText(result.NotOrganizedReason, fontMain);
                    row.Cells[4].MergeRight = 2;
                    row.Cells[4].Format.Alignment = ParagraphAlignment.Center;
                }
            }
            document.LastSection.Add(tableResult);

            //フッター作成
            var paraFooter = new Paragraph();
            paraFooter.AddPageField();
            paraFooter.AddText(" of ");
            paraFooter.AddNumPagesField();
            paraFooter.AddText(" Page");
            paraFooter.Format.Alignment = ParagraphAlignment.Center;
            sectionMain.Footers.Primary.Add(paraFooter);

            //レンダリングしてPDFを出力
            PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true);
            pdfRenderer.Document = document;
            pdfRenderer.RenderDocument();
            using (MemoryStream ms = new MemoryStream())
            {
                pdfRenderer.PdfDocument.Save(ms);
                return File(ms.ToArray(), "application/pdf", "sample.pdf");
            }
        }
    }
}
using PdfSharp.Fonts;
using System;
using System.IO;
using System.Reflection;

namespace MigraDocSample
{
    // 日本語フォントのためのフォントリゾルバー
    public class JapaneseFontResolver : IFontResolver
    {
        private static readonly string YUMIN_TTF =
            "MigraDocSample.fonts.YUMIN.TTF";

        public byte[] GetFont(string faceName)
        {
            switch (faceName)
            {
                case "YUMIN":
                    return LoadFontData(YUMIN_TTF);
            }
            return null;
        }

        public FontResolverInfo ResolveTypeface(
                    string familyName, bool isBold, bool isItalic)
        {
            var fontName = familyName.ToLower();

            switch (fontName)
            {
                case "yumin":
                    return new FontResolverInfo("YUMIN");
            }

            // デフォルトのフォント
            return PlatformFontResolver.ResolveTypeface("Arial", isBold, isItalic);
        }

        // 埋め込みリソースからフォントファイルを読み込む
        private byte[] LoadFontData(string resourceName)
        {
            var assembly = Assembly.GetExecutingAssembly();
            string[] names = assembly.GetManifestResourceNames();
            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
            {
                if (stream == null)
                    throw new ArgumentException("No resource with name " + resourceName);

                int count = (int)stream.Length;
                byte[] data = new byte[count];
                stream.Read(data, 0, count);
                return data;
            }
        }
    }
}
Sample.XXXはサンプル用のデータです。
フォントリゾルバーに登録するファイル名は大文字小文字を区別しますので間違えると機能しません。
また、フォントリソースを忘れずに「埋め込みリソース」にする事も注意が必要です。

英文はパラグラフ内で自動的に改行されるのですが、日本語が改行されないのは上手く解決できませんでした。

この他にもPDFSharpを利用してHTMLからPDFを出力するHTML Rendererというものもあります。


以上メモまで。


2018年4月16日月曜日

ASP.NET MVC デフォルトの T4 Scafolding Template の場所 【Visual Studio 2017】



こちらを参考にカスタムのT4テンプレートの作成を試みているのですが、Visual Studio 2017ではここに書かれてある場所と違うようです。

たぶんここ(かな?)

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates



2017年2月24日金曜日

ASP.NET MVC の AntiForgeryToken がIE,Edgeでエラー

ASP.NETにはCSRF対策にTokenを発行して検証してくれる機能がありますが、IEとEdgeでだけエラーになり、FirefoxとChromeでは大丈夫、しかもデバッグ時にはIEやEdgeでもエラーにならないという不可思議な現象に悩まされました。

必要な偽造防止 Cookie "__RequestVerificationToken" が存在しません。

結構ハマってしまったのですが、原因はこれでした。

Cookie を使用するドメインでは、ドメイン名およびサーバー名に英数字 ("-" または ".") だけを使用しなければなりません。サーバー名にアンダースコア ("_") など、その他の文字が含まれている場合、Internet Explorer は Cookie をブロックします。

デプロイ先のテスト環境のドメインに「test_xxxx」とアンダースコアが含まれていたのが原因でした。
結構古くからの常識のようで、まだまだ勉強不足を痛感します。

以上メモまで。


2015年2月8日日曜日

【C#】都道府県コード順の列挙型都道府県

public enum Prefecture
    {
        北海道 = 1,
        青森県 = 2,
        岩手県 = 3,
        宮城県 = 4,
        秋田県 = 5,
        山形県 = 6,
        福島県 = 7,
        茨城県 = 8,
        栃木県 = 9,
        群馬県 = 10,
        埼玉県 = 11,
        千葉県 = 12,
        東京都 = 13,
        神奈川県 = 14,
        新潟県 = 15,
        富山県 = 16,
        石川県 = 17,
        福井県 = 18,
        山梨県 = 19,
        長野県 = 20,
        岐阜県 = 21,
        静岡県 = 22,
        愛知県 = 23,
        三重県 = 24,
        滋賀県 = 25,
        京都府 = 26,
        大阪府 = 27,
        兵庫県 = 28,
        奈良県 = 29,
        和歌山県 = 30,
        鳥取県 = 31,
        島根県 = 32,
        岡山県 = 33,
        広島県 = 34,
        山口県 = 35,
        徳島県 = 36,
        香川県 = 37,
        愛媛県 = 38,
        高知県 = 39,
        福岡県 = 40,
        佐賀県 = 41,
        長崎県 = 42,
        熊本県 = 43,
        大分県 = 44,
        宮崎県 = 45,
        鹿児島県 = 46,
        沖縄県 = 47

    }


ASP.NET MVC 5.1では、Razorに列挙型の情報をもとにドロップダウンリストボックスを生成するEnumDropDownListメソッドが追加されました。
上記のような都道府県の列挙型クラスを用意して以下のように渡してやれば

@Html.EnumDropDownListFor(model => model.Prefecture)

以下のように展開されます。

<select data-val="true" id="Prefecture" name="Prefecture">
<option value="1">北海道</option>
<option value="2">青森県</option>
<option value="3">岩手県</option>
<option value="4">宮城県</option>
<option value="5">秋田県</option>
・
・
・
</select>

列挙型にいちいち値を指定しているのは、都道府県コードに一致させたいためです。
(値を指定しないと列挙型の内部的な値は0,1,2・・・となります)
HTMLに展開された時にドロップダウンリストのvalueの値が列挙型の内部の値になるため、
都道府県コードと合わせておいてやるとAjaxZip3なんかの郵便番号自動補完に対応することができます。


2013年10月19日土曜日

【Entity Framework】同時実行制御(楽観ロック)を行う (Edit画面にhiddenを追加する)

Entity Framework で同時実行制御を行うにはTimestamp属性をつけるだけでEFが勝手にやってくれます。
(Timestamp属性をつけておけば、ConcurrencyCheckはいらない・・・たぶん)

HogeEntity.cs
public class HogeEntity
    {
        public int HogeEntityId { get; set; }
        public string Name { get; set; }
        public string Value { get; set; }

        [Timestamp]
        [ConcurrencyCheck]
        public byte[] Timestamp { get; set; }
    }


Scaffoldingでコントローラーとビューを作った時はEdit画面にHiddenフィールドを追加してあげないとエラーになります。

Edit.cshtml
@Html.HiddenFor(model => model.Timestamp)

2013年4月5日金曜日

MVC Music Store で Edit ができない

ASP.NET MVC のサンプルアプリケーションとして紹介されている
「MVC Music Store」ですが、現在ASP.NET MVC3に対応したバージョン3が公開されております。

【ASP.NET】MVC Music Store Tutorial
http://www.asp.net/mvc/tutorials/mvc-music-store

【CodePlex】MVC Music Store
http://mvcmusicstore.codeplex.com/

ただし、チュートリアル通りに進めていくと、管理画面のEditのところで、
OptimisticConcurrencyExceptionが発生しエラーとなってしまいます。


原因は Album Model が AlbumId をバインドしないようになっているからです。

Album.cs
namespace MvcMusicStore.Models
{
    [Bind(Exclude = "AlbumId")]  //←ココ
    public class Album
    {
        [ScaffoldColumn(false)]
        public int AlbumId { get; set; }

        [DisplayName("Genre")]
        public int GenreId { get; set; }
...


解決するには、この部分を消してしまうか、
Album.cs
namespace MvcMusicStore.Models
{
    //[Bind(Exclude = "AlbumId")]
    public class Album
    {
        [ScaffoldColumn(false)]
        public int AlbumId { get; set; }

        [DisplayName("Genre")]
        public int GenreId { get; set; }
...

コントローラー側で別途バインドしてやる必要があります。
StoreManagerController.cs
namespace MvcMusicStore.Models
{
    [Authorize(Roles = "Administrator")]
    public class StoreManagerController : Controller
    {
        ...

        //
        // POST: /StoreManager/Edit/5

        [HttpPost]
        public ActionResult Edit(Album album, int id)
        {
            if (ModelState.IsValid)
            {
                album.AlbumId = id;  //←ココ
                db.Entry(album).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
            ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
            return View(album);
        }

        ...


【参考】
http://mvcmusicstore.codeplex.com/workitem/6648

2013年2月3日日曜日

Visual Studio 2012 「コントローラーに移動」がない

ASP.NET MVC 開発でビューとコントローラーを移動する便利な機能が
Visual Studio にあります。
(「ビューに移動」「コントローラーに移動」 Go to View / Go to Controller (Ctrl-M Ctrl-G))

が、Visual Studio 2012 に「コントローラーに移動」が見当たりません(泣)




同様の症状の方も居るみたいですが、バグなのでしょうか・・・。
http://forums.asp.net/t/1840247.aspx/
http://connect.microsoft.com/VisualStudio/feedback/details/775830/go-to-controller-option-missing-from-the-right-click-context-menu

ちなみに、ショートカットキー(Ctrl-M, Ctrl-G)を打つと
「現在使用できないコマンドにバインドされています」
と出てエラーになります。

2012年2月10日金曜日

ASP.NET MVC3 EF Modelからデータベースが作成できない

以下のサイトを参考にASP.NET MVC3 EF Code First を学習しています。

@IT ASP.NET MVC入門【バージョン3対応】

ところがModelからデータベースを作成するところで、以下のようなエラーが出てしまいつまづいてしまいました。

Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.
記事の中で
なお、本稿ではSQL Server Compact 4.0を前提としているので、プロバイダ名は「System.Data.SqlServerCe.4.0」としているが、従来のSQL Serverに接続するならば、「System.Data.SqlClient」とすればよい。
とあったので、

  <connectionStrings>
    <add name="MyMvcContext"
         connectionString="Data Source={servername};
                           Initial Catalog={dbname};
                           Integrated Security=True"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

web.configの記述を上記のようにしたのですが、
この時にデータベース名(上記{dbname}の部分)に
既存のデータベースを指定したのが問題だったようです。
未作成のデータベースを指定することで、解決致しました。

ただし、完全にCodeFirstでデータベースを作成できる場合は良いのですが、
別口からデータベースを操作したり、既存のデータベースとの連携だったり
下記[参考]にあるようにMembership Providerとの連携だったりを考えた場合に
ちゃんと動くのか心配です。
自分はまだ学習段階なのでおいおい解決することを期待・・・。

[参考]
EF 4.1 Code First and Existing Database and .NET Membership
mvc3 code-first error on sqlexpress