読者です 読者をやめる 読者になる 読者になる

だるろぐ

とてもだるだるした日記です http://about.daruyanagi.jp/

WebMatrix とおさらばして、Visual Studio 2015 で ASP.NET Web Pages をはじめる

WebMatrix ASP.net Web Pages Visual Studio

f:id:daruyanagi:20170212020533p:plain

長年愛用してきた「WebMatrix」ですが、昨年10月に2017年11月1日 でのサポート終了がアナウンスされました。

Hi everyone

After a long and successful run, Microsoft has decided to end formal support of WebMatrix. Formal support will end on November 1st, 2017. Community support will continue on the WebMatrix forums

Please take a look at Visual Studio Code, our new, free, open source, multi-platform editor! VS Code support git integration, extensions and a whole bunch of other great features!

Thanks!

The WebMatrix team

WebMatrix formal support ends November 1st, 2017 : The Official Microsoft IIS Forums

f:id:daruyanagi:20170212020959p:plain

すでにテンプレートをダウンロードする際に 404 が発生することが多くなったほか、拡張機能のダウンロード提供が終了しており、第一線で使うにはつらい状況になっています。そろそろ乗り換えを検討すべきでしょう。

Microsoft は後継ソフトとして「Visual Studio Code」を推奨していますが、これは統合ターミナルでバリバリとコマンドを打つ感じなので、GUI に甘やかされた僕にはしんどい感じ(最近「Express」を少し触っているのですが、そっちの文化にあわせるなら割と使いやすいですけどねー)。いずれ慣れないといけないなーとは思うんですが、APS.NET Web Pages を使うならば、当面の間は「Visual Studio 2015」が一番楽かなーって感じです。

1. 「Visual Studio 2015」で ASP.NET プロジェクトを作成

f:id:daruyanagi:20170212021454p:plain

まず「Visual Studio 2015」で ASP.NET プロジェクトを作成します。

f:id:daruyanagi:20170212021543p:plain

プロジェクトタイプは“Empty”でよいです。というか、「WebMatrix」でいうところのスターターテンプレートの類は「Visual Studio」に用意されていないので、“Empty”が無難な気がします。

2. プロジェクトに Razor ページを追加

f:id:daruyanagi:20170212021735p:plain

このテンプレートは本当にほぼ空なので、プロジェクトのコンテキストメニューなどから Web ページ(Razor)を追加する必要があります。

f:id:daruyanagi:20170212021905p:plain

“Razor”などのキーワードで探すと簡単。いろいろあるけど、わかんなかった“Web ページ(Razor v3)”でいいと思います。

f:id:daruyanagi:20170212022148p:plain

最初のページを追加すると、ASP.NET Web Pages に必要な参照が勝手に追加されます。すごーい!

3. [F5]キーを押して実行

とりあえずなんか書いて実行してみましょう。

<!DOCTYPE html>
@{ 
    var message = "Hello! World";
}
<html>
    <head>
        <title></title>
    </head>
    <body>
        <p>@message</p>
    </body>
</html>

[F5]キーを押すとサーバー&ブラウザーが立ち上がります。

f:id:daruyanagi:20170212022322p:plain

message を変えてブラウザーをリロードすると、即座に反映されまっする。なんとなく気軽で「WebMatrix」を使い続けてきましたが、機能面では「Visual Studio」のほうがずっと強力(ブレークポイントとかもしかけられるやで。入力補完はちょっと緩いところあるけど)です。……で、「Visual Studio Code」ではこの手順をどうやるんだ? 

最後に「WebMatrix」さん、長いことありがとうございました。

WebMatrix:フィードを読み込むときに System.Xml.XmlException が発生する

WebMatrix ASP.net Web Pages

ASP.NET Web Pages 製の BOT が、ある日を境に突然、System.Xml.XmlException エラーを吐くようになった。

The element with name 'RDF' and namespace 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' is not an allowed feed format.

某サイトのリニューアルで、RSS 2.0 が RSS 1.0 になったせいでフィードが読めなくなったらしい/(^o^)\

Classes That Model Syndication Feeds and Items

  • SyndicationFeed - represents a syndication feed. Has properties like Title, Description, Links, and Items. The Items property represents the collection of content items expressed in the feed.
  • SyndicationItem - represents a specific syndication feed item and includes properties like Title, Summary, PublishDate, Authors, and so on.

Classes That Transform Syndication Feeds To/From XML

  • Rss20FeedFormatter - can take a SyndicationFeed object and turn it into XML that conforms to the RSS 2.0 specification. Also, can be used to consume a properly-formatted RSS 2.0 feed, turning the XML into a SyndicationFeed object with its properties set based on the data in the consumed XML.
  • Atom10FeedFormatter - same as the Rss20FeedFormatter, but uses the Atom 1.0 standard.
Syndicating and Consuming RSS 1.0 (RDF) Feeds in ASP.NET 3.5 - 4GuysFromRolla.com

Rss10FeedFormatter は標準で用意されていないみたいなので、自分で実装する必要がある。

幸い、コードが GitHub に転がっていたので拝借(見覚えのあるアイコンの人だなぁ……)。おおきにさんきゅーやで!

f:id:daruyanagi:20160603190721p:plain

これを以下のように呼び出してやれば、解決。めでたしめでたし。

try
{
    feed = SyndicationFeed.Load(reader);
}
catch
{
    // エラーがでたら RSS 1.0 ってことにしておく
    var formatter = new Rss10FeedFormatter();
    formatter.ReadFrom(reader);
    feed = formatter.Feed;
}

WebMatrix:改修工廠の早見表がほしかったので作ってみた

艦これ WebMatrix ASP.net Web Pages

f:id:daruyanagi:20150919201617p:plain

今週は超忙しい&体調がよろしくなかった“ので”、合間を見つけて前々からほしかった改修工廠の早見表を作ってみた。接続詞が間違っているというツッコミが入りそうだけど、こういうのって、そういうときにこそやりたくならない?

最初に作ったヤツ

f:id:daruyanagi:20150919201737p:plain

ASP.NET Web Pages + SQL Server Compact で作ってみたけど、だいぶ遅かった。遅いのは多分、自分が SQL わかってないせいだと思う(SELECT でごっそりとってきたデータを LINQ で加工するとかいうわけのわからないことをやっていた)。SQL が分かんないのは一朝一夕に改善できないので、とりあえずデータベースへの問い合わせ結果をキャッシュしまくってみたけれど、スタートアップの遅さは改善できない。Web サイトがスタンバイ(スリープ? なに?)したら、キャッシュを一から再構築しなきゃいけないのも困った。

――というわけで、廃棄する予定。

二番目に作ったヤツ

f:id:daruyanagi:20150919202146p:plain

で、ちょっと考えてみたんだけど、こういうデータっていうのは稀にあるサーバーのメンテナンスのときにしか更新されないわけだ。だったら、なにもデータベースに入れる必要はなかった(CURD のうち R しかやらへんやん?)。JSON か何かでデータを用意しておいて、サーバーのスタートアップ時に読み込めばいい。

俺ってアホだなーと思いながら、ぐちゃぐちゃっと今日半日で作ったら(ロジック組むより、データ打ち込む方がよっぽど時間かかった)、最初に作ったヤツよりだいぶ早くて満足。コードを整理しながらロジック見直せばもうちょっと早くなりそう。なんせ今のは cshtml に foreach が腐るほど埋まってるという正真正銘のクソコードだし……ちょうどいいから今度 GitHub にあげて、GitHub Flow ってのを勉強するネタにしようと思う。

ほんとうはこれを Windows Phone に移植しておでコンに出したかったけれど、いつの間にか締め切り過ぎてたみたい。残念。艦これ Android 版が出るらしいし、Android アプリにするのもアリかなぁ? 

WebMatrix: URL にドットを含めたい

WebMatrix ASP.net Web Pages

f:id:daruyanagi:20150913032211p:plain

Wiki エンジンなんかを作るときなど、「ドット(.)」を URL に含めたい場合は、Web.config に一行、以下のように加えるといいみたい。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
    </system.webServer>
</configuration>

静的リソースまでアプリケーションで処理するようになる(?)ので、効率が悪そうだけど。もっとちゃんと対策したければ、以下の URL が参考になりそう。

「Visual Studio Community」で ASP.NET Web Pages をはじめる

ASP.NET Web Pages

f:id:daruyanagi:20150705212532p:plain

みんなも大好きな「WebMatrix」ですが、そろそろ本格的に“なかったこと”になっているような気がしてならない今日この頃。代わりとなるのはおそらく「Visual Studio Code」なのでしょうが、まだちょっとベータ版なので、今回は定評のありまくる「Visual Studio Community」で ASP.NET Web Pages をはじめる方法を調べてみました。「WebMatrix」で“空のサイト”に相当するものを作るのが今回の目標です。

とりあえずプロジェクトを作成する

f:id:daruyanagi:20150705213348p:plain

まずはプロジェクトを作成する必要があります。プロジェクトの新規作成ダイアログで[Templates]-[Visual C#]-[Web]-[Visual Studio 2012]とツリーを辿り、「ASP.NET Empty Web Application」を選択します。Visual Basic じゃないと死んでしまう病に冒されている人は、[Visual C#]の代わりに[Visual Basic]を選択するとよいでしょう。

f:id:daruyanagi:20150705213553p:plain

ちなみに、[Templates]-[Visual C#]-[Web]にある「ASP.NET Web Application」テンプレートを使っても構いません。

f:id:daruyanagi:20150705213747p:plain

このテンプレートを選択すると、プロジェクトの種類なんかを選べるダイアログが現れるので、ここで「Empty」を選択すればさっきと同じ結果になると思います(厳密にくらべたわけじゃないから知らんけど)。このダイアログからプロジェクトを作ると Azure Web Sites も同時に作れるので、必要な場合はこっちを選ぶと手間が省けるかも。

ページの追加

f:id:daruyanagi:20150705214139p:plain

プロジェクトを作成したら、ページの追加。コンテストメニューを開いて[Add]-[MVC 5 View Page (Razor)]を選択します。

f:id:daruyanagi:20150705214317p:plain

あとは名前を付けると、cshtml ファイルが生成されます。ASP.NET(Web Pages)の流儀にしたがって、最初のファイルの名前は Default.cshtml にしておきましょうか。中身はこんな感じです。

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
    
    </div>
</body>
</html>

body が空っぽなので、ついでにこんな感じでサンプルコードを加えておきます。

@{
    Layout = null;
    var message = "Hello! World"; // 追加
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
        @message <!-- 追加 -->
    </div>
</body>
</html>

これで[F5]キーを押せば、"Hello! World" と書かれたサイトが立ち上がるはず――

f:id:daruyanagi:20150705214739p:plain

――だったのですが、ダメでした。http://go.microsoft.com/fwlink/?LinkId=254126 を読めと言われるのでそれに目を通してみますと、Web.config で利用する ASP.NET Web Pages のバージョンを指定しろと書いてあります。仕方ないので、言われたとおりにキーを追加。

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>

  <appSettings> <!-- このセクションを追加 -->
    <add key="webPages:Version" value="2.0" />
  </appSettings>
</configuration>

f:id:daruyanagi:20150705215117p:plain

すると、サイトが立ち上がりました! めでたしめでたし! あとは SQL CE データベースを読み書きできるようにしたり、その中身を見るためのよさげなツールを探したり(クッソめんどくせー!)、追加の NuGet パッケージを入れたりするだけですね。これで WebMatrix を窓からポイできます。スターターサイトなんかは、Yeoman かなにかで準備する感じになるのかなぁ……ちょっとずつ新しい流儀に慣れていかないとね。

おまけ

ASP.NET Web Pages は .NET 言語で PHP っぽく Web ページのロジックを記述できるフレームワークです。PHP よりも安全に作られているので、お仕事で使わなければならないかわいそうな人でもなければ、こっちの方がお勧めデス。

書き方は @shibayan のサイトでも参考にしてください。PHP の記法と比べながら簡単に解説してくれています。

「(1)」って書いてあるのに続編がないのは気にしないでおきましょう。あとは

なんかが詳しいかもしれません。

WebMatrix:フィードを読み込んでデータベースへつっこむときに System.Data.SqlServerCe.SqlCeException が発生する。

WebMatrix ASP.net Web Pages SQL CE

だいぶ悩んで、Visual Studio まで立ち上げていろいろデバッグしていたのだけど、原因は簡単だった。

datetime

300 分の 1 秒、つまり 3.33 ミリ秒の精度で、1753 年 1 月 1 日から 9999 年 12 月 31 日までの日付と時刻のデータを格納するデータ型です。値は .000、.003、または .007 ミリ秒の単位になるように丸められます。

2 つの 4 バイト整数として格納されます。最初の 4 バイトは、base date である 1900 年 1 月 1 日からの日数、またはこの日までの日数を格納します。基準日とは、システムが参照する日付です。datetime 型の値には、1753 年 1 月 1 日より前の日付を使用できません。もう一方の 4 バイトは、午前 0 時から数えた時間をミリ秒単位で格納します。秒の有効範囲は 0 から 59 までです。

データ型

f:id:daruyanagi:20150625045042p:plain

一方、C# の default(DateTime)0001/01/01 0:00:00。つまり、SyndicationFeed オブジェクトの LastUpdateTime プロパティあたりにちゃんと値がセットされてなくて(そういうフィードを配信しているサイトは割とある)、default(DateTime) を返してくるとき、それをそのまま SQL CE データベースに格納しようとするとエラーになる。

f:id:daruyanagi:20150625050249p:plain

SQL CE の datetime 型を扱う場合は、事前に値の範囲に収まるかチェックして、ダメな場合はハネておかないといけないんだね。

var min_date = new DateTime(1753, 1, 1); // ほんとは readonly でどこかに
var updated_at = item.LastUpdatedTime.UtcDateTime < min_date 
    ? new DateTimeOffset(DateTime.Now).UtcDateTime 
    : item.LastUpdatedTime.UtcDateTime;

// Database.Execute();

教訓

ちゃんとマニュアルは読もう。

WebMatrix 3:oEmbed ヘルパーを作ってみた(2)

WebMatrix ASP.net Web Pages

WebMatrix 3:oEmbed ヘルパーを作ってみた - だるろぐ の続き。今回は Flickr の埋め込みをやってみようかと思う。

~/App_Code/OEmbed.cshtml

@helper Flickr(string url) {
    const string API_ENDPOINT = "http://www.flickr.com/services/oembed/";

    using (var downloader = new WebClient())
    {
        try
        {
            // URL を組み立てて JSON の oEmbed データを取得
            var request = string.Format("{0}?url={1}&format={2}", API_ENDPOINT, url, "json");
            var oembed_data = downloader.DownloadString(request);
            var oembed_json = Json.Decode(oembed_data);

            @ObjectInfo.Print(oembed_json) // デバッグのため

            var embed_type = oembed_json.type as string;

            switch (embed_type) // photo と video の二種類がある
            {
                case "photo":
<figure>
    <img src='@oembed_json.url' alt='@oembed_json.title'>
    <figcaption>
        <img src='http://favicon.qfor.info/f/@oembed_json.provider_url' />
        <a href='@oembed_json.web_page'>@oembed_json.title</a>
        by <a href='@oembed_json.author_url'>@oembed_json.author_name</a>
    </figcaption>
</figure>
                    break;
                case "video":
<figure>
    @Html.Raw(oembed_json.html)
</figure>
                    break;
                default:
                    break;

            }
        }
        catch (Exception exception)
        {
            <p class='error'>@url: @exception.Message</p>
        }
    }
}

~/Default.cshtml

<!DOCTYPE html>

<html lang="ja">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <meta charset="utf-8" />
        <title>マイ サイトのタイトル</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    </head>
    <body>
        @OEmbed.Flickr("https://www.flickr.com/photos/daruyanagi/6219334657/")
        @OEmbed.Flickr("https://www.flickr.com/photos/dmartinie/5760711397/")
    </body>
</html>

結果

たとえば Photo の場合。Twitter のときみたいに html を返してくれないので、自分で組み立てる。

f:id:daruyanagi:20140812194342p:plain

<figure>
    <img src='https://farm7.staticflickr.com/6162/6219334657_ba91a4498d_z.jpg' alt='SMSはやく使えるようになりたい'>
    <figcaption>
        <img src='http://favicon.qfor.info/f/https://www.flickr.com/' />
        <a href='https://www.flickr.com/photos/daruyanagi/6219334657/'>SMSはやく使えるようになりたい</a>
        by <a href='https://www.flickr.com/photos/daruyanagi/'>daruyanagi</a>
    </figcaption>
</figure>

Video の場合。これは html があるのでそれを使う。

f:id:daruyanagi:20140812194506p:plain

<figure>
    <object type="application/x-shockwave-flash" width="500" height="281" data="https://www.flickr.com/apps/video/stewart.swf?v=145061" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=5f7c3bff83&photo_id=5760711397&flickr_show_info_box=true"></param> <param name="movie" value="https://www.flickr.com/apps/video/stewart.swf?v=145061"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="https://www.flickr.com/apps/video/stewart.swf?v=145061" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=5f7c3bff83&photo_id=5760711397&flickr_show_info_box=true" height="281" width="500"></embed></object>
</figure>

f:id:daruyanagi:20140812194912p:plain

写真の方は CSS でいい感じにデコってみた。なかなかいいかも。