3

サンプル テーブル プロファイル プロバイダーをhttp://www.asp.net/downloads/sandbox/table-profile-provider-samplesから新しい MVC 2 サイトに追加しようとしています。

少し調べたりいじったりした後、このようなプロファイル クラスにたどり着きました。

namespace MyNamespace.Models
{
    public class UserProfile : ProfileBase
    {
        [SettingsAllowAnonymous(false),CustomProviderData("FirstName;nvarchar")]
        public string FirstName
        {
            get { return base["FirstName"] as string; }
            set { base["FirstName"] = value; }
        }

        [SettingsAllowAnonymous(false),CustomProviderData("LastName;nvarchar")]
        public string LastName
        {
            get { return base["LastName"] as string; }
            set { base["LastName"] = value; }
        }

        public static UserProfile GetUserProfile(string username)
        {
            return Create(username,false) as UserProfile;
        }

        public static UserProfile GetUserProfile()
        {
            return Create(Membership.GetUser().UserName,true) as UserProfile;
        }
    }
}

そして、次のようなweb.config

<profile enabled="true" defaultProvider="TableProfileProvider" inherits="MyNamespace.Models.UserProfile">
  <providers>
    <clear />
    <add name="TableProfileProvider" type="Microsoft.Samples.SqlTableProfileProvider" connectionStringName="ContentDB" table="aspnet_UserProfiles" applicationName="/"/>
  </providers>
</profile>

途中でわかったと思うことは、

  • <profile>MVC でカスタム プロバイダーを使用するには、web.configの要素に "inherits" 属性が必要です。これにより<properties><add ....>、同じプロファイル フィールド名を持つコンストラクトを使用できなくなります。
  • サンプル SQL テーブル プロファイル プロバイダーにはCustomProviderData属性が必要ですが、上記の理由により、web.config ファイルに表示されないため、属性としてプロファイル クラスのプロパティに追加する必要があります。

ユーザーがログインすると、すべて正常に動作するようです。ただし、新しいユーザー登録プロセスの一環としてプロファイル データを取得したいのですが、ユーザーがログインするまでプロファイル オブジェクトにアクセスできないようです。

MVC テンプレート コードの新しいユーザー登録セクションに、プロファイル データを保存するための呼び出しを追加しようとしました。

FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName);
profile.FirstName = "Doug";
Profile.Save();
return RedirectToAction("Index", "Home");

ただしMembership.GetUser()、ユーザーが実際にログインするまではnullのようです。モデルのユーザー名も使用してみました。

FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
UserProfile profile = UserProfile.GetUserProfile(model.UserName);
profile.FirstName = "Doug";
profile.Save();
return RedirectToAction("Index", "Home");

これはもう少し先のことですが、FirstName プロファイル フィールドを設定しようとすると失敗し、「属性を匿名ユーザーとして設定しようとしていますが、これは許可されていません」という行に沿ったエラー メッセージが表示されます (申し訳ありませんが、アクセスできません)。これを入力している正確なメッセージに)。

これを回避する方法はありますか?FormsServer.SignInフォーム認証に関する限り、メソッドは実際にユーザーをログインさせないように見えます。完全にログインするにはラウンドトリップが必要であり、おそらく Cookie をサーバーに送信する必要があります。

これを回避する簡単な方法がない場合は、データ アクセス メソッド (aspnet_UserProfiles に挿入 ....) を使用して、プロファイル テーブルに直接データを入力することができます。これは行き過ぎた橋でしょうか、それとも実行可能な解決策でしょうか?


誰もこの問題を抱えていませんか?いいえ?私だけ!

更新するために、フランシ・ペノフがこの投稿への回答で提案したことを試しました。

だから、今私のコードはこのようになります。

            FormsService.SignIn(model.UserName, false /* createPersistentCookie */);

            GenericIdentity id = new GenericIdentity(model.UserName);
            HttpContext.User = new GenericPrincipal(id, null);

            UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName) as UserProfile;
            profile.FirstName = "Doug";
            profile.Save();

            return RedirectToAction("Index", "Home");

現在、少なくとも Membership.GetUser() の呼び出しは有効なMembershipUserオブジェクトを返しますが、FirstName プロファイル プロパティを設定しようとすると、メッセージが表示されます。This property cannot be set for anonymous users.

そのため、メンバーシップに関する限り、ユーザーはログオンしていますが、プロファイル システムはまだログオンしていないと考えています。

何か案は?

4

2 に答える 2

4

万歳!

この投稿をさらに詳しく読んで、プロファイルの Initialize メソッドを明示的に呼び出してみようと思いましたが、うまくいきました!

登録アクション メソッドの最終的な完全なコードは次のとおりです。

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

        if (createStatus == MembershipCreateStatus.Success)
        {
            FormsService.SignIn(model.UserName, false /* createPersistentCookie */);

            GenericIdentity id = new GenericIdentity(model.UserName);
            HttpContext.User = new GenericPrincipal(id, null);

            UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName) as UserProfile;
            profile.Initialize(Membership.GetUser().UserName, true);
            profile.FirstName = "Doug";
            profile.Save();

            return RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
        }
    }

    // If we got this far, something failed, redisplay form
    ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
    return View(model);
}

お役に立てれば。

ダグ

于 2010-06-23T13:04:41.100 に答える
0

私は問題に対して少し単純なアプローチをとっています。

web.config ファイルで次のように設定します。

<profile enabled="true">
  <providers>
    <clear />
    <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
  </providers>
  <properties>
    <add name="InfoID" />
    <add name="FirstName" />
    <add name="LastName" />
    <add name="Address" />
    <add name="City" />
    <add name="State" />
    <add name="PostalCode" />
    <add name="Country" />
    <add name="Phone" />
  </properties>
</profile>

私の AccountController クラスでそれを更新するには、次を使用しました。

var user = db.UserInformations.FirstOrDefault(u => u.InfoID == infoID);
var profile = Request.RequestContext.HttpContext.Profile;
profile.Initialize(register.UserName, true);
profile.SetPropertyValue("InfoID", user.InfoID.ToString());
profile.SetPropertyValue("LastName", user.LastName);
profile.SetPropertyValue("FirstName", user.FirstName);
profile.SetPropertyValue("Address", user.Address);
profile.SetPropertyValue("City", user.City);
profile.SetPropertyValue("State", user.State);
profile.SetPropertyValue("Country", user.Country);
profile.SetPropertyValue("PostalCode", user.PostalCode);
profile.SetPropertyValue("Phone", user.Phone);
profile.Save();

文字列キーを使用する代わりに、動的ラッパーを作成し、プロファイル変数で初期化できます。

これは私にとってはうまくいきます。指定されたユーザーの標準 aspnet_Profile データベースを更新します。あるログイン システムから標準のログインに変換しているので、追加の InfoID フィールドがあります (別のデータベースにリンクしています)。ログイン時にこれを行い、情報を転送します。

ログイン時にフィールドを不必要に設定する前に、特定のユーザーの情報がいずれかのフィールドに存在するかどうかを確認するか、変更が必要なフィールドのみを更新する必要があります。

注: 最初にプロファイルを初期化する必要があります。そうしないと、変更によってイエロー スクリーン エラーが発生します。

于 2014-07-24T16:00:25.430 に答える