WebSurfer's Home

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

SQL Server Express 更新時のトラブル

by WebSurfer 2011年12月17日 16:01

SQL Server 2008 Express を利用していますが、Service Pack を適用すると、毎回以下のようなエラーメッセージが表示され、接続できなくなるというトラブルに悩まされてきました。

"ユーザー インスタンスのプロセスを起動中のエラーにより、Sql Server のユーザー インスタンスを生成できませんでした。接続は閉じられます。"

次に Service Pack を適用する際また同じ問題が出ると思いますが、そのころには解決策を忘れてしまうので、自分のブログに備忘録として書いておきます。

SQL Server Express のデータファイル

SQL Server Express は上の画像に表示された mdf, ldf ファイルを自動的に作ります。具体的なことは分かりませんが、Service Pack の適用によってこれらのファイルとの整合が取れなくなることが原因のようです。これらを全部削除してしまえば問題は出なくなります。

Vista の場合、フォルダの場所は以下の通りです。

C:\Users\アカウント名\AppData\Local\Microsoft\Microsoft SQL Server Data\SQLEXPRESS

ユーザーインスタンスを使わない(接続文字列の User Instance を False にする)ことでも問題を回避できるそうです。ただ、それは解決にはなっていないですよね。

Tags:

SQL Server

Web アプリケーションプロジェクトと Profile

by WebSurfer 2011年12月4日 16:34

Web アプリケーションプロジェクトで新規ユーザー登録をする際に、ユーザーの漢字の氏名、住所などのユーザープロファイル情報を取得し、ASP.NET プロファイルを使用して保存する方法の紹介です。

プロファイル情報の取得

先の記事 ユーザー登録時のプロファイル情報取得 では、Web サイトプロジェクトを利用しました。その場合は、どのページでも Profile プロパティでプロファイル・データにアクセスできるようになります。

例えば、以下のように、String 型の KanjiName を profile の properties の add 要素 に定義したとします。

<profile>
  <properties>
    <add name="KanjiName" />
  </properties>
</profile>

すると、ProfileBase クラス を継承する ProfileCommon クラスが自動的に作成され、profile の properties の add 要素 に定義されているそれぞれのプロパティの get/set アクセサが ProfileCommon クラスに追加されます。以下のような感じになると思います。(実際に自動生成されたコードを見たわけではないので想像ですが)

public class ProfileCommon : ProfileBase
{
  public virtual string KanjiName 
  {
    get
    {
      return (String) HttpContext.Current.Profile.
                        GetPropertyValue("KanjiName");
    }

    set
    {
      HttpContext.Current.Profile.
        SetPropertyValue("KanjiName", value);
    }
  }
}

さらに、各ページに、ProfileCommon クラスのインスタンスを取得するため、以下のような Profile プロパティが自動的に追加されます。

protected ProfileCommon Profile
{
  get
  {
    return (ProfileCommon)this.Context.Profile;
  }
}

それゆえ、Web サイトプロジェクトでは、コードは一行も書かなくても、どのページでも Profile.KanjiName プロパティを使ってプロファイル・データにアクセスできるようになります。

しかしながら、Web アプリケーションプロジェクトではそうはいきません。(Web アプリケーションプロジェクトと Web サイトプロジェクトの違いについては MSDN ライブラリ を参照してください)

何故なら ProfileCommon クラスや Profile プロパティは自動的に定義されないからです。

そのあたりのことは、MSDN ライブラリの チュートリアル : Visual Studio の Web サイト プロジェクトから Web アプリケーション プロジェクトへの変換 の「プロファイル オブジェクト コードの変換」のセクションに説明があります。

KanjiName の場合を例に取ると、以下のように手動で ProfileCommon を定義する必要があります。この場合、ProfileCommon は ProfileBase を継承する必要はありません。

public class ProfileCommon
{
  public virtual string KanjiName 
  {
    get
    {
      return (String) HttpContext.Current.Profile.
                        GetPropertyValue("KanjiName");
    }

    set
    {
      HttpContext.Current.Profile.
        SetPropertyValue("KanjiName", value);
    }
  }
}

次に、ProfileCommon クラスのインスタンスの 1 つである Profile を、次のコード例のように、プロファイル システムを使用する必要があるページに追加します。

public partial class _Default : System.Web.UI.Page
{
  ProfileCommon Profile = new ProfileCommon();

  protected void Page_Load(object sender, EventArgs e)
  {
    string kanjiName = Profile.KanjiName;
    if (String.IsNullOrEmpty(kanjiName))
    {
      Label1.Text = "漢字名は設定されていません。";
    }
    else
    {
      Label1.Text = Server.HtmlEncode(kanjiName);
    }            
  }

  protected void Button1_Click(object sender, EventArgs e)
  {
    if (User.Identity.IsAuthenticated)
    {
      Profile.KanjiName = TextBox1.Text;
      Label1.Text = Server.HtmlEncode(Profile.KanjiName);
    }
    else
    {
      Label2.Text = "ログインしていないと設定できません。";
    }
  }
}

なお、web.config に、データベースとのプロファイル・データのやり取りのためプロバイダの設定は必要です。以下の providers の設定は、Visual Studio 2010 が自動的に生成する profile 要素の例です。profile の properties の add 要素に KanjiName を設定する必要はありませんの設定も必要です(2011/12/6 誤記訂正。下の追記参照)。anonymousIdentification の設定は不要です。

<profile>
  <providers>
    <clear/>
    <add name="AspNetSqlProfileProvider" 
      type="System.Web.Profile.SqlProfileProvider" 
      connectionStringName="ApplicationServices" 
      applicationName="/"/>
  </providers>
  <!-- やはり KnajiName の設定は必要 -->
  <properties>
    <add name="KanjiName" />
  </properties>
</profile>

以上の手順で、認証済みユーザーのプロファイルの取得、設定はできるようになります。

ただし、新規ユーザー登録をする際に、ユーザーの漢字の氏名などの情報を取得し、プロファイルを使用して保存する場合は Profile.KanjiName = TextBox1.Text; のようにしてもうまくいきません。

何故なら、その時点ではまだユーザーが認証されていないので、SetPropertyValue メソッドで例外がスローされてしまうからです。

以下のように、ProfileBase.Create メソッド を使って指定したユーザー名のプロファイルのインスタンスを作成し、それを操作するとうまくいきます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Profile;

namespace WebApplication1.Account
{
  public partial class CreateUser : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      CreateUserWizard1.ContinueDestinationPageUrl = 
        Request.QueryString["ReturnUrl"];
    }

    protected void CreateUserWizard1_CreatedUser(
      object sender, EventArgs e)
    {
      ProfileBase profile =
        ProfileBase.Create(CreateUserWizard1.UserName, true);
      profile.SetPropertyValue(
        "KanjiName", lastName.Text + " " + firstName.Text);            
      profile.Save();

      FormsAuthentication.SetAuthCookie(
        CreateUserWizard1.UserName, false);

      string continueUrl = 
        CreateUserWizard1.ContinueDestinationPageUrl;
      if (String.IsNullOrEmpty(continueUrl))
      {
        continueUrl = "~/";
      }
      Response.Redirect(continueUrl);
    }
  }
}

---------- 2011/12/6 追記 ----------

先に作ったプロジェクトでは、何故か KanjiName の設定がなくても問題ありませんでした。

しかし、新たに別プロジェクトを作って、同様なコードを試してみたところ、KanjiName の設定がないと Profile.KanjiName プロパティで以下の例外がスローされます。

"System.Configuration.SettingsPropertyNotFoundException: 設定プロパティ 'KanjiName' が見つかりませんでした。"

理由は不明です(調査中)。違いは、先に作ったプロジェクトは .ASPXANONYMOUS クッキーが発行されること(anonymousIdentification は設定してないのに)と、開発マシンの Vista の IIS7 上で動かしていること(新たに作った方は開発サーバー)の 2 点ぐらいです。後者は関係なさそうですが、前者が怪しい感じです。

Tags:

ASP.NET

Froms 認証クッキーの永続化

by WebSurfer 2011年12月3日 13:29

ASP.NET 標準の Forms 認証に使用される認証クッキーの「永続化」については、先の記事 永続的ってデフォルトで 30 分? に書きましたが、続けて「永続化」した時としない時の動作の違いを備忘録として書いておきます。

まず、ログインに成功した時にサーバーからブラウザに送られる認証クッキーですが、「永続化」した場合は以下のよう expires によって有効期限が指定されます。「永続化」しない場合は認証クッキーに expires=...; が存在しません。

Set-Cookie: .ASPXAUTH=...; expires=Wed, 30-Nov-2011 13:21:29 GMT; path=/; HttpOnly

expires の日時は、ログインに成功した時点から authentication の forms 要素 の timeout 属性で設定した時間(デフォルトで 30 分)だけ先の日時になります。

認証クッキーは認証チケットの入れ物に過ぎないことに注意してください。認証チケットの有効期限は、ユーザー名などの他の情報と一緒に暗号化されて、認証チケットの中に含まれています。

[永続化」した場合の認証クッキーの有効期限は、認証チケットの有効期限と同じになりますが、認証クッキーの有効期限で認証チケットの有効期限を判定しているわけではありません(そもそも、サーバー側ではクライアントから送られてきたクッキーの有効期限はわかりません)。

認証チケットが発行された以降、有効な認証チケットがブラウザからの要求と一緒にサーバーに送られてくれば、サーバーはユーザーを認証済みと見なし、匿名アクセスが許可されてないページへのアクセスを許可します。

認証チケットが送られてこない場合、もしくは送られてきた認証チケットが期限切れの場合、サーバーはユーザーをログイン画面へリダイレクトします。

slidingExpiration が true になっている場合、timeout 属性で設定した時間の半分を過ぎてアクセスすると、有効期限が延長された認証チケット/クッキーが再発行されます。「永続化」している場合は、expires=...; も延長されて認証クッキーが再発行され、クライアントの HDD 上の既存の認証クッキーが上書きされます。

認証クッキーを「永続化」した場合としない場合(即ち、認証クッキーの有効期限の有無)では、以下のように動きが異なります。

「永続化」した場合

クッキーに有効期限がある(即ち、Set-Cookie: に expires=...; が指定される)ので、ブラウザはクッキーを HDD に保存します。

ブラウザを閉じたり Windows をシャットダウンしたりしても、再度ブラウザを立ち上げてアクセスすれば、ブラウザは認証クッキーを HDD から取得してサーバーに送ります。

クッキーの有効期限が切れると、ユーザーが次にサイトを訪問した時にブラウザによって削除されます。

次回アクセスする際にログイン操作の手間が省けるということが「永続化」のメリットですが、timeout をデフォルトの 30 分程度の短い時間に設定した場合はほとんど意味がないです。

ちなみに、BlogEngine.NET のオリジナルの web.config では timeout="129600"(90 日)に設定してありました。「永続化」もこのぐらい長ければ役に立つと思いますが。

でも、セキュリティ上は、timeout をできるだけ短い時間に、ついでに slidingExpiration は false に設定しておく方がよさそうです。

「永続化」しない場合

この場合、認証クッキーはブラウザのメモリにしか保持されません。従って、ブラウザを閉じれば認証クッキーは消えます。

逆に、ブラウザを閉じなければ認証クッキーは消えません。要求のたびに送られ続けます。(ただし、中身の認証チケットが有効かどうかは別の話で、timeout の設定によります)

Tags: , ,

Authentication

About this blog

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

Calendar

<<  2024年5月  >>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar