「Asp.Net」を含む日記 RSS

はてなキーワード: Asp.Netとは

2009-05-14

IIS+ASP.NET+SQLite

自分のための覚え書き。知ってる人からすれば全然当たり前のことかも…

IIS上で、Visual Studio 2008で開発したASP.NETWebサイトを動かす時に、SQLiteを使う方法

IISの動作しているマシンに「SQLite for ADO.NET 2.0」をインストール

それだけで良いと思ったけれど、以下のエラーが発生。

ArgumentException: 要求された .Net Framework データ プロバイダが見つかりません。これは、インストールされていない可能性があります。

いろいろ調べたら、手動でmachine.configを書き換える必要があるみたい。

そこで、machine.configに以下の行を追加。

	<system.data&gt;
		<DbProviderFactories&gt;
			<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.61.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /&gt;
		</DbProviderFactories&gt;
	</system.data&gt;

無事に動くようになりました。

2009-02-19

モダンPerl入門』を第1章だけ読んだ

巷のPerl Mongerな人たちの間で話題の『モダンPerl入門』を読み始めた。

第1章はオブジェクト指向トレンドの話で、とても興味深く読んだのだが、同時に「なんでこれPerlで実装せなあかんの?」と疑問に思った。ていうかオブジェクト指向やりたいならJavaC#でいいじゃん。

Perl5には本格的なOOPの仕組みが実装されていない。

継承という基本的な概念もないし、コンストラクタなんかも用意されていない。ゆえに、MooseとかのCPANモジュールを使って実装しなければいけないのだけれど、その分敷居が高くなって初心者には判りづらい。初心者でも現場に投入できるような、強力なオブジェクト指向機構が用意されているJavaC#といった言語StrutsASP.NETといったフレームワークなんかとは全然違う。

私はメインPHPASP.NET(C#)という人間で、Perlバッチプログラムとかクローラの実装とか雑用処理なんかに使っている。PHPは小規模プロジェクトアジャイルな開発がしたい時、ASP.NETは大規模プロジェクトに呼ばれた時用の懐刀という感じで使い分けている。PerlWebサービスを作ることももちろん出来るけれども、どちらかというとスピードが優先される開発に用いるものだと思うし、OOPを用いた大規模なプロジェクトPerlを使おうとする理由がよく判らない。無駄に難しいし、そもそも本書を読めるレベルPerlを理解している人の頭数がかなり少ないだろうから、実装しても保守コストがやたらかかる。Livedoormixiはてなのような大規模サイトPerlで動いているようだが。。。

モダンPerl入門』は内容も書き方も素晴らしい良書だけれど、その辺りが引っかかった。「PerlOOPを使う理由(APS.NETStruts+Java採用しない理由)」は何なのだろうか? 私のプログラマーとしてのスキルが低いだけだと思うが、よく判らないので誰か教えてくだしあ。教えてダンコーガイ

2008-02-27

Joel On Software私訳

訳してみた。あらためて、和訳はものすごく時間を要する作業だということがわかった。もうしないと思う。

注意:以下は意訳、適当訳、稚拙訳であり、誤訳を多々含んでいることは確実であり、Joel氏が本当に以下のように述べているとは限りません。

なぜMicrosoft Officeファイルフォーマットはこんなにもややこしいのか (そしてその対処法を幾つか)

Tuesday, February 19, 2008

先週、MicrosoftOfficeバイナリフォーマットを公開したが、このフォーマットは殆ど正気でないように見える。Excel 97-2003ファイルフォーマットは349ページのPDFファイルだ。でも待って、それで全部じゃない。このドキュメントには次の面白いコメントが書いてある。

それぞれのExcelワークブックは1つのcompound fileに収められている

つまり、Excel 97-2003ファイルはOLE coumpound documentで、それは結局、1つのファイル内にあるファイルシステムである。これは、理解するのにあと9ページはスペックを読まなくちゃならないぐらいには十分に複雑だ。そしてこれらの「スペック」は、普通我々が考えるようなスペックというよりは、Cデータ構造みたいに見える。これ全体が階層的ファイルシステムなのだ。

もしあなたが週末を、Wordドキュメントブログインポートしたり、あなたの個人的な財務データからExcelフォーマットスプレッドシートを生成するような気の利いたコードを書くのに使おうと思ってこれらのドキュメントを読み始めたなら、このスペックのややこしさと長さがそんな気をあっという間に失せさせるだろう。普通プログラマはこのOfficeバイナリファイルフォーマットについて次のような結論を下す:

この4つ全てについて、きみは間違っている。ちょっとだけ掘り下げて、これらのファイルフォーマットがどうしてこんなに信じがたいくらいに複雑なのか、なぜMicrosoftの悪いプログラミングを反映しているのではないのか、そしてそれを回避するためにあなたに何ができるか、を明らかにしよう。

理解すべき最初のことは、これらのバイナリファイルフォーマットはちょっと違ったデザインゴールを持って設計されたということだ。たとえばHTMLとは。

これらはすごく古いコンピュータで速く処理できるようにデザインされた。Excel for Windowsの初期のバージョンでは、1MBのRAM、20MHz動作の80386が Excelを快適に走らせることができるための妥当なものだった。このファイルフォーマット内には、ファイルを素早く開いたり閉じたりするための最適化が沢山仕込まれている:

これはライブラリを使うことを想定して設計されている。もしあなたがバイナリインポートするものを1から書き上げたいと思ったら、Windows Metafile Format (何か図を描く場合) や OLE Counpound Storage みたいなものをサポートしなくてはいけなくなる。もしあなたが Windows上でやるのなら、そうしたことをたいしたことのない作業にするためのライブラリサポート存在する... そういったフィーチャーを使うことは(元々)マイクロソフトチームのためのショートカットだった。でもあなたが全部を自分でスクラッチから書くなら、全部の作業を自分自身でやらなくてはいけない。

オフィスはcompound documentsに対して広範囲のサポートを持っている。例えば、スプレッドシートWord文書に埋め込んだりできる。完璧Wordファイルフォーマットのparserは、同じように、埋め込まれたスプレッドシートで何かインテリジェントなことが出来るべきだろう。

それは相互協調性(interoperability)を意識してデザインされてはいない。仮定されていたのは、WordファイルフォーマットWordからのみ読み書きされなくてはいけない、ということで、それは当時においては十分に合理的なものだった。これは、Wordチームのプログラマファイルフォーマットをどう変更するかについて決定を行う場合にはいつでも、彼らが気にするのは (a)何が高速か (b)Wordコードベースにおいて最小の行数になるのは何か、だったことを意味する。SGMLHTML-interchangeableといった標準ファイルフォーマットのようなアイデアは、最初にインターネットドキュメントの相互交換を実現するまで現実のものにはならなかった。それはOfficeバイナリフォーマットが最初に考案されてから10年後のことだったのだ。ドキュメントを交換するのにインポーターエクスポーターを使うことができるという仮定が常にあった。実際Wordは簡便な交換のために設計されたRTFと呼ばれるフォーマットを持っており、そのフォーマットは殆ど最初のころからあり、今も100%サポートされている。

それはアプリケーションの全ての複雑さを反映していなくてはいけない。 全部のチェックボックス、全部のフォーマッティングオプション、そして全部の、Microsoft Officeのフィーチャーは、ファイルフォーマットのどこかで叙述されていなくてはいけない。Wordパラグラフメニューにある、"Keep With Next" と呼ばれるチェックボックス、これはパラグラフを、その後ろのパラグラフと同じページに置くのに必要な場合は、次のページに移動させるもの(?)だが、これもファイルフォーマットの中に無くてはいけない。そしてこれはつまり、あなたがWordドキュメントを正しく読み込める完璧Wordクローンを実装したいなら、そういったフィーチャーを実装しなくてはいけないということだ。Wordドキュメントをロードする競争力のあるワードプロセッサを作っているのなら、ファイルフォーマットからそのビットをロードするコードを書くのには1分しかかからないかもしれないが、ページのレイアウトアルゴリズムをそれに対応させるのに何週間もかかるかもしれない。もしあなたがそうしない場合、カスタマーがあなたのクローンWordファイルを読み込んだら、全部のページがぐちゃぐちゃになってしまうだろう。

それはアプリケーション歴史を反映していなくてはいけない。 このファイルフォーマットに見られる多くの複雑さは、古く、複雑で、愛されず、めったに使われないフィーチャーを反映している。それらはファイルフォーマットのなかに後方互換性のためにまだあり、そしてMicrosoftにとってその辺りのコードを残しておくことには何らコストはかからない。しかしあなたがこれらのファイルフォーマットをparseおよびwriteする一貫した完全な仕事をしたいと思うなら、Microsoftインターンが15年前にやったのと同じことを全て、またやらなくてはいけない。要点は、何千人年の仕事が今のWordExcelには費やされてきたのであり、これらのアプリケーション完璧クローンを作りたいと本当に欲するなら、あなたは何千人年を費やさなくてはならないことになる、ということだ。ファイルフォーマットは単に、アプリケーションサポートする全てのフィーチャーの簡潔なサマリーなのだ。

手始めに、小さな例を一つ、深く見てみよう。Excelのワークシートは色々なタイプのBIFFレコードの集まったものだ。私はスペックの一番最初のBIFFを見てみたい。1904と呼ばれるレコードだ。

Excelファイルフォーマット仕様のこのレコードについての記述は非常に曖昧なものだ。そこでは単に、1904レコードが「1904日付システムが使われているかどうか」を示すレコードだ、と述べているだけだ。ああ、使えない仕様書の典型的な一例だ。あなたがExcelファイルフォーマットで何かしている開発者で、そしてファイルフォーマット仕様にこう書いてあるのを見つけたなら、あなたがMiocrosoftは何かを隠しているのだと結論付けたとしても無理はない。この情報の断片は十分な情報をあなたに与えはしない。あなたには幾ばくか外部の情報が必要で、私は今ここで、それを提供しよう。Excelワークシートには、2種類ある。日付のエポックが1900/1/1のもの(これには、Lotus 1-2-3 との互換性のために故意に入れられた閏年に関するバグがあるが、ここでそれについて述べるのは退屈すぎる)、および、1904/1/1のものだ。Excelは両方をサポートしているが、それはExcelの最初のバージョンMac版であり、それは単に簡単だったという理由でOSエポックを使っていて、しかしWindows版のExcel1-2-3ファイルインポートできなくてはならず、そしてそれは1900/1/1をエポックとして採用していたからだ。あなたが涙ぐむのも無理はない。歴史のどの時点においても、プログラマが正しいことをしなかった、という時はないのだが、しかし現実にあなたが手にしているものはこれなのだ。

1900と1904のファイルタイプは両方とも世の中には広く存在しており、それは通常、ファイルWindowsMacのどちらで作られたかによる。一方のタイプから他方のタイプへ黙って変換するのはIntegrity的に問題があるので、Excelファイルタイプを変換することをしない。Excelファイルをparseするためには、あなたは両方を扱わなくてはならない。それはファイルからこのbitをロードするだけの問題ではなく、あなたが日付表示と両方のエポックを扱うparsingのコードまで書き直さなくてはいけないということを意味する。実装には何日かかかるだろうと私は思う。

実際、あなたがExcelクローンの作業をするなら、日付の扱いについて、あらゆる種類の微妙ディティール発見することになるだろう。Excelは日付の値をいつ変換するのか? 表示の整形はどうやっているのか? なぜ1/31は今年の January 31と翻訳され、また一方で1/50はJanuary 1st, 1950と翻訳されるのか? Excelソースコードと同じだけの量のドキュメントを書かないがぎり、振る舞いに関しての微妙ビットを全て完全に記述することはできない。

そしてこのレコードは、あなたが扱う何百もあるBIFFレコードの最初の1つに過ぎず、しかももっとも単純なものなのだ。他のレコードの殆どは、より多くのプログラマーを涙に暮れさせるぐらいには十分複雑だ。

唯一導き得る結論はこれだ。

MicrosoftMicrosoftOfficeファイルフォーマットリリースしたことは大変有用なことだが、しかしそれでOfficeファイルフォーマットインポートしたり保存したりするのが楽になるということは全く無さそうだ。それらは狂気じみて複雑で、リッチアプリケーションで、そしてあなたは人気のある20%の部分を実装して80%の人々を幸せにするというくらいのことしかできない。バイナリファイル仕様によってなされるのは、多く見積もっても、著しく複雑なシステムリバースエンジニアリングにかかる時間を何分か削減するくらいだろう。

オーケー, 私はいくつか回避法を教えると約束した。良いニュースは、殆どの良く知られたアプリケーションにとって、Officeバイナリファイルフォーマットを読み書きしようと試みることは誤った決定だということだ。あなたが真剣に考えなくてはいけない代案が2つある。Officeそのものにそれをやらせるか、書き込むのが簡単なファイルフォーマットを使うかだ。

ヘビーな仕事Officeにやらせよう。WordExcelは実に完全なオブジェクトモデルを持っており、COMオートメーションの手段が可能で、これであなたは何でもプログラムでやるようにできる。多くのシチュエーションでは、Office内のコードを再利用するほうがそれを実装しようとするよりも良い。ここにいくつか例がある。

  1. Webベースアプリケーションがあって、それが既存のWordファイルPDFフォーマットに出力するようにする必要がある場合、それを実装するにはこうする: ファイルを読み込んでからWord 2007のビルトインのPDFエクスポーターを使ってそれをPDFとして保存する、数行のWord VBAコードだ。あなたはこのコードIISで動作しているASPASP.NETコードから直接呼び出す。これでうまくいく。最初にWordを立ち上げるときは数秒かかる。2回目はCOMサブシステムによりWordはまたあなたがそれを必要としたときのためにメモリ中にキープされている。それは通常のWebベースアプリケーションにとっては十分に速い。
  2. 上と同じ。ただしあなたのWebホスティング環境Linuxだった場合。フルライセンスWordインストールされたWindows 2003サーバを買う。そしてその仕事をする小さなWebサービスを構築する。C#ASP.NETでの半日の作業だ。
  3. 上と同じ、ただしあなたがよりスケールさせたいと望む場合。ステップ2で構築した全部のボックスの前にロードバランサーを置きなさい。コードは必要ない。

この手のアプローチは、全ての種類の一般的なOfficeタイプについての、サーバ上であなたがやりたいと思うであろうアプリケーションで、うまくいくだろう。例えば:

これらのケースの全てにおいて、Officeオブジェクトインタラクティブ動作でないことを教えてやる方法があり、だから表示をアップデートするのに煩わされたり、ユーザ入力を促す必要はない。ところで、このようなやりかたでいく場合には、gotchas(?)がいくつかあり、そしてそれはMicrosoftは公式にサポートしているものではない。だからあなたがそれを始める前にはKnowledge baseの記事を読むように。

書き込むファイルにはもっとシンプルフォーマットを使いなさい。単にOfficeドキュメントプログラムで生成したいなら、殆どいつでもOfficeバイナリフォーマットよりももっと良いフォーマットWordExcelでも問題なく開くことができるようなフォーマット存在する。

いずれにせよ、全てのOfficeファイルを完全に読み書きできるような、文字通りのOffice競合製品を作ろうとする(その場合には、何千年もの作業があなたに予約される) のでない限り、Officeバイナリフォーマットの読み書きをするというのは、何であれあなたが解決しようとしている問題を解決するためのもっとも労働集約的な方法だ。

2007-10-30

[]55行で作るC#テンプレートエンジン

http://anond.hatelabo.jp/20071030034313二番煎じ

あまりのアホさに、作ってて気が狂いかけた

方針


using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.CSharp;

delegate void ConvertTemplateDelegate(TextWriter tw, Dictionary<object, object> args);
static class TemplateGenerator {
    public static ConvertTemplateDelegate Generate(string code) {
        CompilerParameters param = new CompilerParameters();
        param.GenerateInMemory = true;
        param.ReferencedAssemblies.Add("System.Web.dll");
        CompilerResults rs = new CSharpCodeProvider().CompileAssemblyFromSource(param, ParseTemplate(code));
        if (0 < rs.Errors.Count) {
            StringWriter sw = new StringWriter();
            sw.WriteLine("Compile Error...");
            foreach (CompilerError err in rs.Errors)
                sw.WriteLine(err.ToString());
            throw new Exception(sw.ToString());
        }
        return (ConvertTemplateDelegate) Delegate.CreateDelegate(typeof(ConvertTemplateDelegate), rs.CompiledAssembly.GetType("Template", true).GetMethod("Convert"));
    }
    private static string ParseTemplate(string code) {
        using (StringWriter sw = new StringWriter()) {
            sw.WriteLine("using System; using System.Collections.Generic; using System.IO; using System.Web;");
            sw.WriteLine("public static class Template {");
            sw.WriteLine("public static void Convert(TextWriter tw, Dictionary<object, object> args) {");
            int index = 0;
            while (0 <= index &amp;&amp; index < code.Length) {
                int i = code.IndexOf("<%", index);
                sw.WriteLine("tw.Write(\"{0}\");", EscapeString(i < 0 ? code.Substring(index) : code.Substring(index, i - index)));
                if (0 <= i) {
                    i += 2;
                    int i2 = code.IndexOf("%>", i);
                    if (0 <= i2) {
                        string cc = code.Substring(i, i2 - i);
                        if (cc.StartsWith("="))
                            sw.WriteLine("tw.Write(HttpUtility.HtmlEncode(\"\"+({0})));", cc.Substring(1));
                        else
                            sw.WriteLine(cc);
                        i = i2 + 2;
                    }
                }
                index = i;
            }
            sw.WriteLine("}}");
            return sw.ToString();
        }
    }
    private static string EscapeString(string code) {
        return code.Replace("\\", "\\e").Replace("\"", "\\\"").Replace("\t", "\\t").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\\e", "\\\\");
    }
}

サンプル C# コード。ためしにテンプレートから Xml 生成して、標準出力してみる。

class Program {
    static void Main(string[] args) {
        ConvertTemplateDelegate func = TemplateGenerator.Generate(TemplateEngine.Resource1.template);
        using (StringWriter sw = new StringWriter()) {
            Dictionary<object, object> arg = new Dictionary<object, object>();
            arg["title"] = "template sample";
            arg["data"] = new string[] { "foo", "fooo", "<strong>foooooooooo!</strong>" };
            func(sw, arg);
            Console.WriteLine(sw);
        }
    }
}

サンプルテンプレート

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title><%= args["title"] %></title>
  </head>
  <body>
    <h1><%= args["title"] %></h1>
    <table>
<% string[] data = (string[]) args["data"]; %>
<% for(int i = 0; i < data.Length; i++) { %>
      <tr bgcolor="<%= i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>">
        <td><%= i %></td>
        <td><%= data[i] %></td>
      </tr>
<% } %>
    </table>
  </body>
</html>

出力例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>template sample</title>
  </head>
  <body>
    <h1>template sample</h1>
    <table>


      <tr bgcolor="#FFCCCC">
        <td>0</td>
        <td>foo</td>
      </tr>

      <tr bgcolor="#CCCCFF">
        <td>1</td>
        <td>fooo</td>
      </tr>

      <tr bgcolor="#FFCCCC">
        <td>2</td>
        <td>&lt;strong&gt;foooooooooo!&lt;/strong&gt;</td>
      </tr>

    </table>
  </body>
</html>

CodeDom 使って動的コンパイル……って、このコードのままだとセキュリティ的に大問題な気がするな。

素直に ASP.NET 使ったほうが楽だと直感した。

あと EscapeString すっごく自信ない。たぶん修正が必要だと思うw

2007-09-26

今日、別の会社が書いたASP.NETWebアプリを修正した

ユーザーコントロールフォルダに一度しか使われず再利用がまず不可能なコントロールが山のようにあった

ユーザーコントロールフォルダにはサブフォルダが無かった

aspxはコードビハインドにしてるのに殆どユーザーコントロールを配置してるだけだった

死ねばいいのにと思った

ログイン ユーザー登録
ようこそ ゲスト さん