10

カスタム認証があり、ユーザーがログインすると、セッション/キャッシュに必要な情報が保持されます...

そのため、ユーザー ID でフィルター処理されたデータを表示する必要があるドロップダウンを持つビューがいくつかあります...その結果をフィルター処理する最良の方法を知りたいです...

1 - コントローラに直接?

...   
Model.MyList = repository.GetAll().Where(x => x.User.Id == userId);
return View(Model);

2 - アクション フィルターの作成 (DB から不要なデータを照会せずにそれを行うにはどうすればよいですか)

3 - 他の方法ですか?

1 の問題は、同じドロップダウンを持つ複数のビューがあるため、同じコードを繰り返さなければならないことです。

4

7 に答える 7

10

アプローチ - 1

関数

private void userInfo(ResultExecutingContext filtercontext)
{                                        
    if (filtercontext.Controller.TempData[userId.ToString()] == null)
        filtercontext.Controller.ViewBag.userId =
            filtercontext.Controller.TempData[userId.ToString()] = 
            repository.GetAll().Where(x => x.Id == userId);

    else      //This will load the data from TempData. So, no need to 
              //hit DataBase.
        filtercontext.Controller.ViewBag.userId =
            filtercontext.Controller.TempData[userId.ToString()];

    TempData.Keep();  // This will save your Database hit.
}

フィルター方法

public class MyActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filtercontext)
    {
        //Call the Action Method before executing the View and after 
        //executing the Action.
        userInfo(filtercontext);
        base.OnResultExecuting(filtercontext);
    }
}

コントローラ アクション メソッド

[MyActionFilter] 
//Whenever Action Method will execute. We will check TempData contains 
//Data or not.
public ActionResult Index()
{
    return View();
}

とについてTempDataのポイントTempData.Keep()

  1. のアイテムは、TempData読んだ後にのみ削除のタグが付けられます。
  2. の項目は、TempDataを呼び出すことでタグを解除できますTempData.Keep(key)
  3. RedirectResult内のアイテムを保持するためにRedirectToRouteResult常に呼び出します。TempData.Keep()TempData

変数も使用できますSession。唯一の大きな問題は、Session変数が に比べて非常に重いことTempDataです。最後に、コントローラー/エリア全体でデータを保持することもできます。

TempData変数と同様に、新しいタブ/ウィンドウでも機能します。Session

アプローチ - 2

Cacheデータをいくつかの変数に入れることができ、 で行ったのと同じ方法で再度再利用できますTempData

于 2013-08-11T07:48:12.733 に答える
1

免責事項: 私は Entity REST SDK の作成者です。

私は別のアプローチを取り、クエリを実行する前に適用する必要があるすべての必要なラムダ式を含むセキュリティ コンテキストを作成しました。

    public class DefaultSecurityContext : BaseSecurityContext {

      public static DefaultSecurityContext Instance = new DefaultSecurityContext();

      // UserID for currently logged in User
      public static long UserID{
           get{
                 return long.Parse( HttpContext.Current.User.Identity.Name );
           }
      }

      public DefaultSecurityContext(){
      }

      protected override void OnCreate(){

            // User can access his own Account only
            var acc = CreateRules<Account>();

            acc.SetRead( y => x=> x.AccountID == UserID ) ;
            acc.SetWrite( y => x=> x.AccountID == UserID );

            // User can only modify AccountName and EmailAddress fields
            acc.SetProperties( SecurityRules.ReadWrite, 
                  x => x.AccountName,
                  x => x.EmailAddress);

            // User can read AccountType field
            acc.SetProperties<Account>( SecurityRules.Read, 
                  x => x.AccountType);

            // User can access his own Orders only
            var order = CreateRules<Order>();
            order.SetRead( y => x => x.CustomerID == UserID );

            // User can modify Order only if OrderStatus is not complete
            order.SetWrite( y => x => x.CustomerID == UserID && x.OrderStatus != "Complete" );

            // User can only modify OrderNotes and OrderStatus
            order.SetProperties( SecurityRules.ReadWrite, 
                  x => x.OrderNotes,
                  x => x.OrderStatus );

            // User can not delete orders
            order.SetDelete(order.NotSupportedRule);
      }
}

ご覧のとおり、プロパティへのアクセスもフィルタリングできます。

重複したコードのほとんどがセキュリティ コンテキストに置き換えられた場合、異なるユーザー ロールごとに異なるセキュリティ コンテキストを作成しても、同じコントローラーを維持できます。

public class OrdersController : WebAtomsController <MyEntities> {
        protected override BaseSecurityContext CreateSecurityContext(){
             return DefaultSecurityContext.Instance;
        }

        public ActionResult SearchOrders( 
               string productName, 
               string orderBy = "OrderID DESC", 
               int start = 0, 
               int size = 10)
        {
               // Where method automatically applies
               // filter based on current SecurityContext

               var aq = Where<Order>();
               if(!string.IsNullOrEmpty(productName)){
                      aq = aq.Where( 
                                  x=> x.OrderItems.Any( 
                                     y=> y.Product.ProductName.StartsWith(productName)));
               }

               // OrderBy accepts string as a parameter
               aq = aq.OrderBy(orderBy);
               return aq.Page(start,size).Select( 
                     y=> new {
                            y.OrderID,
                            y.OrderDate,
                            y.OrderStatus,
                     });
        }
}

詳細については、 https://entityrestsdk.codeplex.comをご覧ください。

于 2013-08-13T20:44:44.507 に答える
1

必要な値を ViewBag 内に配置してビューに送信するアクション フィルターを作成するだけです。これにより、同じコードを何度も書き直す必要がなくなり、ビューに集中して必要に応じてデータを表示することができます。サンプルコードについては、以下を参照してください。

using System.Web.Mvc;
namespace CustomActionFilter.CustomActionFilters
{
    public class MyResultFilterAttribute : FilterAttribute, IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            //The action filter logic - before 
            filterContext.Controller.ViewBag.userInfo = GetNeccUserInfo(filterContext.HttpContext.User.Identity.Name);
        }

        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            //The action filter logic - after
        }
    }
    private UserInfo GetNeccUserInfo(string userName)
    {
        using (var repo = new UserRepository(new UniteOfWorkUsers()))
        {
            var userInfo = repo.GetUserInfo(userName);
            return userInfo;
        }
    }
}

これが役立つことを願っています:)

于 2013-08-07T17:22:47.547 に答える
0

たとえば、MembershipLogic クラスを作成し、現在使用している、または将来使用する可能性のあるすべてのメソッドをそこに定義することができます。クラスはユーザー ID ごとにデータを返します

したがって、コントローラーでは次のようになります。

var db = new DbEntities();
List<a> newList = MembershipLogic.UserList(db, userid);

そして MembershipLogic では、次のメソッドが必要です。

public static List<a> UserList(DbEntities db, int UserID)
{
var list = db.GetAll().Where(x => x.Id == userId);
return list;
}

私は自分のプロジェクトでそのようなロジックを使用しています。メソッドを蓄積し、必要なすべての場所でそれらを使用します。

于 2013-08-08T16:23:20.573 に答える
0

userId パラメーターを使用してメソッドを作成するか、このように使用するユーザーの拡張メソッドを作成しないのはなぜですか "User.GetList();" ? リポジトリ パターンに適しているかどうかはわかりません。:)

于 2013-08-13T02:51:42.797 に答える
0

最良の方法: すべてのユーザーのキャッシュされたリストを取得します。+: データベース効率的。-: 大きなテーブルの場合、大量のメモリを使用します。-: 結果が最新ではありません (キャッシュ時間を調整してください)。

OData には、このフィルターを実行するデータベース リクエスト フィルターがありますが、意図したとおりに使用することは意図されていません。これは、このユーザーに許可されていない行を返すストアド プロシージャおよびクエリのエラーから保護するためのものです。これは、データの「漏洩」に対する第 2 レベルの保護です。

var model = new Model(userId)

他の場所:

Model(Guid userID)
{
    MyList = CacheStore.Get("allUsers", () => repository.GetAll())
                .Where(x => x.Id == userId).ToList();
}
于 2013-08-11T13:45:14.443 に答える