WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ASPNETDB.mdf の作り方

by WebSurfer 2012年7月4日 23:20

ASP.NET フォーム認証用のユーザー情報のストアとして SQL Server を用いる場合、サーバーでのデータベースの作り方を備忘録として書いておきます。

開発環境では、開発マシンに Visual Studio と SQL Server がインストールされていれば、Visual Studio の「ASP.NET Webサイト管理ツール」が、フォーム認証用のデータベースファイル ASPNETDB.MDF をアプリケーションルート直下の App_Data フォルダに自動生成してくれます。

自分がサーバーの管理者であれば、開発マシンの ASPNETDB.MDF ファイルをサーバーにコピーして使うことができます。(もしくは、下に述べるデータベース作成用のスクリプトを SQL Server Management Studio を使って実行する手もあります)

しかしながら、ホスティングサービス(レンタルサーバー)を利用している場合は上記のようなことはできません。ホスティングサービス会社に、自分が作った ASPNETDB.MDF を送って SQL Server にアタッチしてもらうのも望み薄です。

では、どうするかと言えば、通常、ホスティングサービス会社が SQL Server の管理ツールを提供しているはずなので、そのツールからスクリプトを走らせることができれば、遠隔地にあるサーバーにデータベースを作成することができるはずです。

以下に、自分が使っているホスティングサービス(ActiveWeb)の場合の例を書きます。ActiveWeb の管理ツールは Plesk と myLittleAdmin です。ExpressWeb の場合も、同じ会社がサービスしているので、手順は大筋で同じです。(他のホスティングサービスの場合は不明です。無責任モードですみません)

  1. まず、ホスティングサービス会社が提供しているツールを使って SQL Server にデータベースを作成し、ユーザーの設定をします。その時点で、データベース名、ユーザー名、パスワードが決まるはずですが、それらは、それぞれ、接続文字列の Initial Catalog、User ID、Password に設定するので覚えておいてください。(接続文字列の Server に設定するサーバー名は、別にホスティングサービス会社より通知されていると思います)
  2. 次に、自分の開発マシンで、aspnet_regsql.exe を利用して、必要な機能(テーブル、ストアドプロシージャ、トリガ)を上記 (1) で作ったデーターベースに追加するための SQL スクリプトファイルを生成します。以下のようにコマンドラインから入力します。この例で、FormsAuth は上記 1 で指定したデータベース名、script.sql は生成する SQL スクリプトファイルの名前です。

コマンドラインから aspnet_regsql を実行

  1. ホスティングサービス会社が提供している SQL Server の管理ツールを使用して、上記 2 で作ったスクリプトを走らせ、データベースにテーブル、ストアドプロシージャ、トリガを作成します。ActiveWeb、ExpressWeb の場合は myLittleAdmin を利用します。下の画像を参照してください。「新しいクエリ」という文字の下にある myLittleAdmin 上のファイルを開くボタン 印のボタンをクリックすると、ファイルを選択するダイアログが開きますので、それでステップ 2 で作ったスクリプトを指定します。

myLitleAdmin でスクリプトの実行

  1. 接続文字列を実環境に合わせて修正します。開発環境は、開発マシンの SQL Server Express に Windows 認証でユーザーインスタンスを利用して接続しているのを、レンタルサーバーでは Express 版でない SQL Server の既定のインスタンスに SQL Server 認証で接続するのが普通だと思います。その場合、接続文字列は以下のようになるはずです。不明な点はレンタルサーバー会社に確認してください。

開発環境(Visual Studio が自動生成)

<connectionStrings>
  <add name="ApplicationServices"
    connectionString=
     "data source=.\SQLEXPRESS;
      Integrated Security=SSPI;
      AttachDBFilename=|DataDirectory|\aspnetdb.mdf;
      User Instance=true"
    providerName="System.Data.SqlClient" />
</connectionStrings>

運用環境

<connectionStrings>
  <add name="ApplicationServices"
    connectionString=
     "Server=サーバー名;
      User ID=ユーザー名;
      Password=パスワード;
      Initial Catalog=データベース名"
    providerName="System.Data.SqlClient" />
</connectionStrings>
  1. ここまでで ASPNETDB.mdf 相当のデータベースが生成され、Web アプリから接続できるようになっているはずです。ただし、データベースのテーブルの中身は空なので、自分でユーザー登録とロールの設定が必要です。

管理用のページを作るなりしないとユーザー登録やロールの設定はできないので、そこが少々面倒かも知れません。参考に、指定されたユーザーを指定されたロールに追加するサンプルコードのある MSDN ライブラリのページ Roles.AddUserToRole メソッド を紹介しておきます。

それが問題であれば、開発環境で作ったユーザー登録やロールが設定済みの ASPNETDB.mdf から、Database Publishing Wizard を利用してスクリプトを生成すれば、上記 5 の手順は不要になるはずです。

Tags:

Authentication

イベントハンドラ

by WebSurfer 2012年7月2日 22:28

C# を使った .NET Framework アプリでのイベントとハンドラの宣言、定義の方法を忘れかけていて余計な時間がかかったので、整理して、備忘録として簡単に書いておきます。

まず、イベントを宣言するには、その前にデリゲート型の宣言が必要です(EventHandler デリゲートのようにクラスライブラリに用意されている場合は不要です)。

C# のデリゲートは、C や C++ の関数ポインタと同じと考えればよいと思います。以下の例は、Object 型と EventArgs 型の引数を持つデリゲート型 ChangedEventHandler の宣言です。

public delegate void 
  ChangedEventHandler(object sender, EventArgs e);

上の構文は、メソッド宣言の構文と同様ですが、delegate キーワードによって、ChangedEventHandler がデリゲート型であることをコンパイラに通知しています。

規約により、.NET Framework のイベントデリゲートは、そのイベントの発生元(上の例では sender)と、そのイベントのデータ(上の例では e)という 2 つのパラメータを持ちます。

デリゲートを定義した後、イベントの実��は以下のように行います。細かい説明はコメントを参照してください。

public class MyClass : ArrayList
{
  // デリゲートを用いてイベントを宣言。クラスの外からは
  // 公開フィールドのように見えるが、アクセスには制限が
  // あり、実行できるのは以下の処理のみ。
  //  ・新しいデリゲートの結合
  //  ・結合されたデリゲートの削除
  public event ChangedEventHandler Changed;

  // イベントを起動するメソッド OnChanged を作成し
  // ておき、必要なタイミングで呼び出す。イベントは、イ
  // ベントを宣言したクラスの中からしか起動できない。そ
  // れゆえ、protected として作成し、派生クラスがイベン
  // トを起動できるようにする。
  protected virtual void OnChanged(EventArgs e)
  {
    // ハンドラがイベントにアタッチされてない場合 null
    // になるので、起動する前に null でない事を確認。
    if (this.Changed != null)
    {
      this.Changed(this, e);
    }
  }

  // 例えば、何かを追加したタイミングでこのイベントを発
  // 生させたいときは、以下のようにする。
  public override int Add(object value)
  {
    int i = 0;
    // 何かの処置
    OnChanged(EventArgs.Empty);
    return i;
  }
}

ここまでの宣言、定義で、MyClass.Add メソッドが起動された時、MyClass.Changed イベントが発生します。

ただし、ハンドラの定義、ハンドラのイベントへのアタッチがないので、それ以上は何も起こりません。

ハンドラの定義とイベントへのアタッチは以下の例のようにします。

public class EventListener
{
  private MyClass _myClass;

  public EventListener(MyClass myClass)
  {
    this._myClass = myClass;
    // ハンドラをイベントにアタッチ
    this._myClass.Changed += 
      new ChangedEventHandler(MyClass_Changed);
  }

  // ハンドラの定義
  private void MyClass_Changed(object sender, EventArgs e)
  {
    // 何かの処理
  }
}

Tags:

.NET Framework

WebBrowser の拡張

by WebSurfer 2012年7月1日 18:04

先の記事 SHDocVw.dll と AxSHDocVw.dll の作り方と使い方 では、ActiveX の WebBrowser コントロール (shdocvw.dll) をホストする、AxHost クラス から派生するラッパーコントロールを Visual Studio で生成し、それ使って NewWindow2 イベントを利用する例を書きました。

それと比較するために、.NET Framework の WebBrowser(これも shdocvw.dll のマネージラッパー)を拡張して同様なことを行うコードを書いてみました。

かなり面倒で、最初は COM の相互運用の知識がなかったのでお手上げ状態でした。あちこちググって調べて、動くようになるまで 3 日ぐらいかかりました。(笑)

詳しくは以下のコードとそのコメントを参照してください。参考にしたページの一覧も書いておきます。(手抜きですみません)

WebBrowser.CreateSink メソッド

Extended .NET 2.0 WebBrowser Control

COM相互運用機能の利用

COM相互運用機能の利用 - パート2

Microsoft .NET/COM の移行と相互運用性

COM ラッパー

ランタイム呼び出し可能ラッパー

COM 相互運用性 - 第 1 部 : C# クライアント チュートリアル

方法: COM ソースによって発生したイベントを処理する

.NET の WebBrowser を拡張したクラス

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Reflection;

namespace WebBrowserExtended
{
  public class MyWebBrowser : WebBrowser
  {
    // WebBrowser の AxtiveX への参照
    private IWebBrowser2 axIWebBrowser2;

    // WebBrowser の AxtiveX が作成されたとき呼び出される
    [PermissionSet(SecurityAction.LinkDemand, 
      Name = "FullTrust")]
    protected override void 
      AttachInterfaces(object nativeActiveXObject)
    {
      this.axIWebBrowser2 = 
        (IWebBrowser2)nativeActiveXObject;
      base.AttachInterfaces(nativeActiveXObject);
    }

    [PermissionSet(SecurityAction.LinkDemand, 
      Name = "FullTrust")]
    protected override void DetachInterfaces()
    {
      this.axIWebBrowser2 = null;
      base.DetachInterfaces();
    }

    public object Application
    {
      get
      {
        if ((this.axIWebBrowser2 == null))
        {
          throw new 
            AxHost.InvalidActiveXStateException(
              "Application",
              AxHost.ActiveXInvokeKind.PropertyGet);
        }

        // この Application プロパティは COM の
        // マネージラッパー
        return this.axIWebBrowser2.Application;
      }
    }

    public bool RegisterAsBrowser
    {
      get
      {
        if ((this.axIWebBrowser2 == null))
        {
          throw new 
            AxHost.InvalidActiveXStateException(
              "RegisterAsBrowser",
              AxHost.ActiveXInvokeKind.PropertyGet);
        }

        // この RegisterAsBrowser プロパティは
        // COM のマネージラッパー
        return this.axIWebBrowser2.RegisterAsBrowser;
      }
      set
      {
        if ((this.axIWebBrowser2 == null))
        {
          throw new 
            AxHost.InvalidActiveXStateException(
              "RegisterAsBrowser",
              AxHost.ActiveXInvokeKind.PropertySet);
        }

        // この RegisterAsBrowser プロパティは
        // COM のマネージラッパー
        this.axIWebBrowser2.RegisterAsBrowser = value;
      }
    }

    // シンクオブジェクトへの参照
    private MyWebBrowserEventSink sink;

    // HTTP 通信の cookie とは関係ないので注意
    private AxHost.ConnectionPointCookie cookie;

    // シンクをサブスクライバ・リストに追加
    [PermissionSetAttribute(SecurityAction.LinkDemand, 
      Name="FullTrust")]
    protected override void CreateSink() 
    {
      base.CreateSink();

      if ((this.axIWebBrowser2 == null)) 
      {
        throw new AxHost.InvalidActiveXStateException(
            "CreateSink",
            AxHost.ActiveXInvokeKind.MethodInvoke);
      }

      this.sink = new MyWebBrowserEventSink(this);
      this.cookie = new AxHost.ConnectionPointCookie(
                          this.axIWebBrowser2,
                          this.sink, 
                          typeof(DWebBrowserEvents2));
    }

    // シンクのサブスクライブを解除
    [PermissionSetAttribute(SecurityAction.LinkDemand, 
      Name="FullTrust")]
    protected override void DetachSink() 
    {
      if (cookie != null) 
      {
        this.cookie.Disconnect();
        this.cookie = null;
      }
      base.DetachSink();
    }

    // NewWindow2 イベントの定義
    public event NewWindow2EventHandler NewWindow2;

    // .NET 側の NewWindow2 イベントを発動するメソッド
    protected virtual void 
      OnNewWindow2(NewWindow2EventArgs e) 
    {
      if ((this.NewWindow2 != null)) 
      {
        this.NewWindow2(this, e);
      }
    }

    // コネクションポイントからの呼び出しを受け取る
    // クライアント・シンクのクラス定義
    [ClassInterface(ClassInterfaceType.None)]
    public class MyWebBrowserEventSink :
      StandardOleMarshalObject, DWebBrowserEvents2
    {
      private MyWebBrowser browser;

      public MyWebBrowserEventSink(MyWebBrowser browser)
      {
        this.browser = browser;
      }

      // COM ソースから発生したイベントから呼び出される
      // メソッド
      public void 
        NewWindow2(ref object ppDisp, ref bool cancel)
      {
        NewWindow2EventArgs e = 
          new NewWindow2EventArgs(ppDisp, cancel);

        // .NET 側の NewWindow2 イベントを発動
        this.browser.OnNewWindow2(e);

        ppDisp = e.PpDisp;
        cancel = e.Cancel;
      }
    }
  }

  // NewWindow2 イベントのハンドラのデリゲート
  public delegate void NewWindow2EventHandler(object sender, 
    NewWindow2EventArgs e);

  // NewWindow2 イベントハンドラ引数のクラス定義
  public class NewWindow2EventArgs : EventArgs
  {        
    public object PpDisp { get; set; }
    public bool Cancel { get; set; }
        
    public NewWindow2EventArgs(object ppDisp, bool cancel)
    {
      this.PpDisp = ppDisp;
      this.Cancel = cancel;
    }
  }

  // DWebBrowserEvents2 インターフェイスの NewWindow2 メ
  // ソッド、IWebBrowser2 インターフェイスの Application
  // プロパティと RegisterAsBrowser プロパティをインポー
  // ト(つまり、マネージラッパーをコンパイル時に生成)。
  // ComImport, InterfaceType, Guid 指定は必須らしい。
  [ComImport, 
  InterfaceType(ComInterfaceType.InterfaceIsIDispatch), 
  Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]
  public interface DWebBrowserEvents2
  {
    [DispId(0xfb)]
    void NewWindow2(
      [In, Out, MarshalAs(UnmanagedType.IDispatch)]
      ref object ppDisp, 
      [In, Out, MarshalAs(UnmanagedType.VariantBool)] 
      ref bool Cancel);
  }

  [ComImport, 
  Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"),
  InterfaceType(ComInterfaceType.InterfaceIsIDispatch), ]
  public interface IWebBrowser2
  {
    [DispId(200)]
    object Application
    {
      [return: MarshalAs(UnmanagedType.IDispatch)]
      get;
    }

    [DispId(0x228)]
    bool RegisterAsBrowser
    {
      get;
      set;
    }
  }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WebBrowserExtended
{
  public partial class Form1 : Form
  {
    private MyWebBrowser browser;
        
    public Form1()
    {
      browser = new MyWebBrowser();
            
      InitializeComponent();
                        
      browser.Dock = DockStyle.Fill;
      this.Controls.Add(browser);
      browser.NewWindow2 += 
        new NewWindow2EventHandler(browser_NewWindow2);
    }

    private void button1_Click(object sender, EventArgs e)
    {
      browser.Navigate(
        "http://msdntestnew/159-HyperLinkToPdf.aspx");
    }

    private void browser_NewWindow2(object sender, 
      NewWindow2EventArgs e)
    {
      Form1 frmWB = new Form1();

      // WebBrowser.AttachInterfaces メソッドは Visible
      // プロパティを true にすると呼び出される。なので、
      // ここで設定しないと RegisterAsBrowser プロパティ、
      // Application プロパティで例外がスローされてしまう。
      frmWB.Visible = true;

      frmWB.browser.RegisterAsBrowser = true;
      e.PpDisp = frmWB.browser.Application;
    }
  }
}

Tags:

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar