কন্ট্রোলারদের জন্য বেস ক্লাসটি ব্যবহার না করে কীভাবে সমস্ত দর্শনের জন্য ভিউব্যাগের বৈশিষ্ট্য সেট করবেন?


96

অতীতে আমি সমস্ত কন্ট্রোলারকে সাধারণ বেস নিয়ামক হিসাবে উত্তরাধিকারসূত্রে প্রাপ্ত হয়ে বিশ্বব্যাপী ভিউডাটা / ভিউব্যাগের উপর বর্তমান ব্যবহারকারীর মতো সাধারণ বৈশিষ্ট্য আটকে রেখেছি।

এটি আমার বেস কন্ট্রোলারে আইওসি ব্যবহার করার অনুমতি দেয় এবং কেবল এই জাতীয় ডেটার জন্য বিশ্বব্যাপী ভাগ করে নেওয়া না।

আমি ভাবছি এমভিসি পাইপলাইনে এই জাতীয় কোড inোকানোর কোনও বিকল্প উপায় আছে কিনা?

উত্তর:


22

আমার দ্বারা অ-চেষ্টা করা হয়েছে, তবে আপনি সক্রিয়করণ প্রক্রিয়া চলাকালীন আপনার মতামতগুলি নিবন্ধভুক্ত করতে এবং তারপরে ভিউ ডেটা সেট করতে পারেন।

দর্শনগুলি অন ফ্লাইতে নিবন্ধীকৃত হওয়ার কারণে নিবন্ধের বাক্য গঠন আপনাকে Activatedইভেন্টের সাথে সংযোগ স্থাপনে সহায়তা করে না , সুতরাং আপনার এটির একটি সেট আপ করা দরকার Module:

class SetViewBagItemsModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistration registration,
        IComponentRegistry registry)
    {
        if (typeof(WebViewPage).IsAssignableFrom(registration.Activator.LimitType))
        {
            registration.Activated += (s, e) => {
                ((WebViewPage)e.Instance).ViewBag.Global = "global";
            };
        }
    }
}

এটি হতে পারে সেই "একমাত্র সরঞ্জামের একটি হাতুড়ি" -র মতামত থেকে আমার টাইপ পরামর্শ; এটি পেতে আরও সহজ এমভিসি-সক্ষম উপায় থাকতে পারে।

সম্পাদনা করুন: বিকল্প, কম কোড পদ্ধতির - কেবলমাত্র নিয়ামকের সাথে সংযুক্ত করুন

public class SetViewBagItemsModule: Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry cr,
                                                      IComponentRegistration reg)
    {
        Type limitType = reg.Activator.LimitType;
        if (typeof(Controller).IsAssignableFrom(limitType))
        {
            registration.Activated += (s, e) =>
            {
                dynamic viewBag = ((Controller)e.Instance).ViewBag;
                viewBag.Config = e.Context.Resolve<Config>();
                viewBag.Identity = e.Context.Resolve<IIdentity>();
            };
        }
    }
}

2 সম্পাদনা করুন: নিয়ামক নিবন্ধকরণ কোড থেকে সরাসরি কাজ করে এমন আরেকটি পদ্ধতির:

builder.RegisterControllers(asm)
    .OnActivated(e => {
        dynamic viewBag = ((Controller)e.Instance).ViewBag;
        viewBag.Config = e.Context.Resolve<Config>();
        viewBag.Identity = e.Context.Resolve<IIdentity>();
    });

ঠিক আমার যা প্রয়োজন ছিল। বাক্সটির বাইরে কাজ করার জন্য উত্তর আপডেট করেছেন
স্কট ওয়েইনস্টাইন

দুর্দান্ত জিনিস - আপনার পদ্ধতির উপর ভিত্তি করে আমি এই মুহুর্তে মডিউলটির প্রয়োজন ছাড়াই আরও একটি সরলীকরণ যুক্ত করেছি।
নিকোলাস ব্লুমহার্ট

এর Resolveঅংশ কি e.Context.Resolve? আমি উল্লেখ করা উচিত আমি Ninject ব্যবহার করছি ...
drzaus

244

অ্যাকশনফিলারঅ্যাট্রিবিউট ব্যবহার করা সবচেয়ে ভাল উপায়। কীভাবে এটি নেট কোর এবং। নেট ফ্রেমওয়ার্কে ব্যবহার করবেন তা আমি আপনাকে দেখাব।

নেট কোর 2.1 এবং 3.1

public class ViewBagActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        // for razor pages
        if (context.Controller is PageModel)
        {
            var controller = context.Controller as PageModel;
            controller.ViewData.Add("Avatar", $"~/avatar/empty.png");
            // or
            controller.ViewBag.Avatar = $"~/avatar/empty.png";

            //also you have access to the httpcontext & route in controller.HttpContext & controller.RouteData
        }

        // for Razor Views
        if (context.Controller is Controller)
        {
            var controller = context.Controller as Controller;
            controller.ViewData.Add("Avatar", $"~/avatar/empty.png");
            // or
            controller.ViewBag.Avatar = $"~/avatar/empty.png";

            //also you have access to the httpcontext & route in controller.HttpContext & controller.RouteData
        }

        base.OnResultExecuting(context);
    }
}

তারপরে আপনার এটি আপনার startup.cs এ নিবন্ধন করতে হবে।

। নেট কোর 3.1

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options => { options.Filters.Add(new Components.ViewBagActionFilter()); });
}

। নেট কোর 2.1

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
        {
            options.Filters.Add(new Configs.ViewBagActionFilter());
        });
}

তারপরে আপনি এটিকে সমস্ত দর্শন এবং পৃষ্ঠায় ব্যবহার করতে পারেন

@ViewData["Avatar"]
@ViewBag.Avatar

। নেট ফ্রেমওয়ার্ক (এএসপি। নেট এমভিসি। নেট ফ্রেমওয়ার্ক)

public class UserProfilePictureActionFilter : ActionFilterAttribute
{

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.Controller.ViewBag.IsAuthenticated = MembershipService.IsAuthenticated;
        filterContext.Controller.ViewBag.IsAdmin = MembershipService.IsAdmin;

        var userProfile = MembershipService.GetCurrentUserProfile();
        if (userProfile != null)
        {
            filterContext.Controller.ViewBag.Avatar = userProfile.Picture;
        }
    }

}

গ্লোবাল আপনার কাস্টম ক্লাস নিবন্ধন করুন। অ্যাস্যাক্স (অ্যাপ্লিকেশন_আরম্ভ)

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        GlobalFilters.Filters.Add(new UserProfilePictureActionFilter(), 0);

    }

তারপরে আপনি এটি সমস্ত দর্শন ব্যবহার করতে পারেন

@ViewBag.IsAdmin
@ViewBag.IsAuthenticated
@ViewBag.Avatar

এছাড়াও একটি অন্য উপায় আছে

এইচটিএমএলহেল্পারে একটি এক্সটেনশন পদ্ধতি তৈরি করা

[Extension()]
public string MyTest(System.Web.Mvc.HtmlHelper htmlHelper)
{
    return "This is a test";
}

তারপরে আপনি এটি সমস্ত দর্শন ব্যবহার করতে পারেন

@Html.MyTest()

9
আমি কেন বুঝতে পারছি না কেন এটি আরও উত্সাহ দেওয়া হয়নি; এটি অন্যদের তুলনায় অনেক কম আক্রমণাত্মক পদ্ধতি
জোশকমলি

4
এটি অনুসন্ধানের জন্য 8 ঘন্টা গবেষণা ... সঠিক উত্তর। তোমাকে অনেক ধন্যবাদ.
ডেল্ট্রি

4
+1 বিশ্বব্যাপী ডেটা সংহত করার জন্য দুর্দান্ত এবং পরিষ্কার উপায়। আমি আমার সাইটের সংস্করণটি সমস্ত পৃষ্ঠায় রেজিস্টার করতে এই কৌশলটি ব্যবহার করেছি।
উইল Bickford

4
উজ্জ্বল, সহজ এবং আপত্তিজনক সমাধান।
ইউজেন টিম

4
তবে আইওসি কোথায়? অর্থাৎ আপনি কীভাবে স্যুইচ আউট করবেন MembershipService?
drzaus

39

যেহেতু ভিউব্যাগের বৈশিষ্ট্য সংজ্ঞা অনুসারে, ভিউ উপস্থাপনা এবং যে কোনও হালকা দেখার যুক্তিযুক্ত যা আবশ্যক হতে পারে তার সাথে আবদ্ধ , তাই আমি একটি বেস ওয়েবভিউপেজ তৈরি করব এবং পৃষ্ঠা সূচনাতে বৈশিষ্ট্যগুলি সেট করব। এটি পুনরাবৃত্তি যুক্তি এবং সাধারণ কার্যকারিতা জন্য একটি বেস নিয়ামক ধারণা মত অনুরূপ, কিন্তু আপনার মতামত জন্য:

    public abstract class ApplicationViewPage<T> : WebViewPage<T>
    {
        protected override void InitializePage()
        {
            SetViewBagDefaultProperties();
            base.InitializePage();
        }

        private void SetViewBagDefaultProperties()
        {
            ViewBag.GlobalProperty = "MyValue";
        }
    }

এবং তারপরে \Views\Web.config, pageBaseTypeসম্পত্তিটি সেট করুন :

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="MyNamespace.ApplicationViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

এই সেটআপটির সমস্যাটি হ'ল যদি আপনি এক ভিউতে ভিউব্যাগের কোনও সম্পত্তিতে মান সেট করে থাকেন এবং তারপরে অন্য ভিউতে এটির অ্যাক্সেস করার চেষ্টা করছেন (আপনার ভাগ করা _ লেআউট ভিউয়ের মতো) তবে প্রথম দর্শনে মান মান সেট করা হবে if লেআউট ভিউ হারিয়েছে।
পেড্রো

@ পেড্রো এটি অবশ্যই সত্য, তবে আমি যুক্তি দিয়ে দেখাব যে ভিউব্যাগটি অ্যাপ্লিকেশনটিতে স্থির রাষ্ট্রের উত্স নয়। আপনার মতো শব্দগুলি সেশন স্থিতিতে চাইবে এবং তারপরে আপনি এটিটি আপনার বেস ভিউ পৃষ্ঠায় টেনে আনতে এবং যদি উপস্থিত থাকে তবে ভিউব্যাগে সেট করতে পারেন।
ব্র্যান্ডন লিন্টন

আপনার একটি বৈধ পয়েন্ট রয়েছে তবে বেশিরভাগ লোকই অন্য ভিউগুলিতে এক দৃষ্টিতে ডেটা সেট ব্যবহার করে; আপনি যখন পৃষ্ঠার শিরোনামটি একটি দৃশ্যে সেট করেন এবং আপনার ভাগ করা লেআউট ভিউ হয় তখন এটি এইচটিএমএল নথির <শিরোনাম> ট্যাগগুলিতে প্রিন্ট করে। এমনকি "মাস্টার" লেআউট ভিউটি এইচটিএমএলের মাথার যথাযথ জেএস উল্লেখগুলি অন্তর্ভুক্ত করার জন্য "সন্তানের" ভিউতে "ভিউব্যাগ.ডাটাট্যাবলসজে" এর মতো বুলিয়ান সেট করে আমি এই পদক্ষেপটি আরও এগিয়ে নিতে চাই like এটি যতক্ষণ না লেআউট সম্পর্কিত, আমি মনে করি এটি করা ঠিক হবে।
পেড্রো

@ পেড্রো শিরোনাম ট্যাগগুলির পরিস্থিতিতে ভালভাবে দেখা যায়, সাধারণত প্রতিটি ViewBag.Titleসম্পত্তি একটি সম্পত্তি নির্ধারণ করে এবং তারপরে ভাগ করা বিন্যাসের একমাত্র জিনিস <title>@ViewBag.Title</title>। বেস অ্যাপ্লিকেশন ভিউ পৃষ্ঠার মতো কোনও কিছুর জন্য এটি যথাযথভাবে উপযুক্ত হবে না যেহেতু প্রতিটি ভিউ পৃথক, এবং বেস ভিউ পৃষ্ঠাটি এমন ডেটার জন্য হবে যা সমস্ত দৃষ্টিতে সত্যই সাধারণ।
ব্র্যান্ডন লিন্টন

@ পেড্রো আমি বুঝতে পারছি আপনি কী বলছেন এবং আমি মনে করি ব্র্যান্ডন সেখানে পয়েন্টটি মিস করেছেন। আমি একটি কাস্টম ওয়েবভিউপেজ ব্যবহার করছিলাম এবং আমি কাস্টম ওয়েবভিউপেজে একটি কাস্টম সম্পত্তি ব্যবহার করে একটি ভিউ থেকে লেআউট ভিউতে কিছু ডেটা দেওয়ার চেষ্টা করেছি। আমি যখন ভিউটিতে সম্পত্তি সেট করি তখন এটি আমার কাস্টম ওয়েবভিউপেজে ভিউডাটা আপডেট করে তবে যখন এটি বিন্যাস ভিউতে পৌঁছে যায় তখন ভিউডাটা এন্ট্রিটি ইতিমধ্যে হারিয়ে যায়। আমি কাস্টম ওয়েবভিউপেজে ViewContext.Controller.ViewData ["কিছু ভ্যালু"] ব্যবহার করে এটি পেয়েছিলাম। আমি আশা করি এটি কাউকে সাহায্য করবে
ইমরান রশিদ

17

ব্র্যান্ডনের পোস্টটি ঠিক টাকার উপরে। বস্তুত হিসেবে, এই এক পা এগিয়ে নিতে এবং বলে যে আপনি ঠিক যেমন আপনার সাধারণ বস্তু যোগ করা উচিত হবে বৈশিষ্ট্য এর বেস WebViewPage যাতে আপনি প্রতিটি দৃশ্যে ViewBag থেকে কাস্ট করার আইটেম হবে না। আমি আমার বর্তমান ব্যবহারকারী সেটআপটি এইভাবে করি।


আমি ত্রুটিটি নিয়ে কাজ করতে পারিনি'ASP._Page_Views_Shared__Layout_cshtml' does not contain a definition for 'MyProp' and no extension method 'MyProp' accepting a first argument of type 'ASP._Page_Views_Shared__Layout_cshtml' could be found (are you missing a using directive or an assembly reference?)
স্প্রিন্টস্টার

এটির জন্য +1, আমি অ-স্থিতিশীল ইউটিলিটি শ্রেণীর একটি উদাহরণ ভাগ করে নেওয়ার জন্য ঠিক এটি করছি যা সমস্ত দর্শনগুলিতে বিশ্বব্যাপী উপলব্ধ হওয়া দরকার।
নিক কোড

9

আপনি একটি কাস্টম অ্যাকশনআরসাল্ট ব্যবহার করতে পারেন:

public class  GlobalView : ActionResult 
{
    public override void ExecuteResult(ControllerContext context)
    {
        context.Controller.ViewData["Global"] = "global";
    }
}

অথবা একটি অ্যাকশন ফিল্টার:

public class  GlobalView : ActionFilterAttribute 
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.Result = new ViewResult() {ViewData = new ViewDataDictionary()};

        base.OnActionExecuting(filterContext);
    }
}

একটি এমভিসি 2 প্রকল্প খোলা ছিল তবে দুটি কৌশলই এখনও সামান্য পরিবর্তনগুলির সাথে প্রয়োগ করে।


5

আপনাকে ক্রিয়াতে বা জালিয়াতি বা মডেলটি পরিবর্তন করতে হবে না, কেবল একটি বেস নিয়ামক ব্যবহার করুন এবং লেআউট ভিউকনস্টেক্সট থেকে বিদ্যমান নিয়ামকটি কাস্ট করুন।

পছন্দসই সাধারণ ডেটা (শিরোনাম / পৃষ্ঠা / অবস্থান ইত্যাদি) এবং ক্রিয়া সূচনা দিয়ে একটি বেস নিয়ামক তৈরি করুন ...

public abstract class _BaseController:Controller {
    public Int32 MyCommonValue { get; private set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

প্রতিটি নিয়ামক বেস নিয়ামক ব্যবহার করে তা নিশ্চিত করুন ...

public class UserController:_BaseController {...

আপনার _Layout.cshmlপৃষ্ঠায় দেখার প্রেক্ষাপট থেকে বিদ্যমান বেস নিয়ন্ত্রকটিকে কাস্ট করুন ...

@{
    var myController = (_BaseController)ViewContext.Controller;
}

এখন আপনি আপনার বিন্যাস পৃষ্ঠা থেকে আপনার বেস নিয়ামকের মানগুলি উল্লেখ করতে পারেন।

@myController.MyCommonValue

3

আপনি যদি নিজের মতামতের বৈশিষ্ট্যগুলির জন্য টাইম চেকিং এবং ইন্টিলিসেন্সটি সংকলন করতে চান তবে ভিউব্যাগটি যাওয়ার উপায় নয়।

একটি বেসভিউ মডেল ক্লাস বিবেচনা করুন এবং আপনার অন্যান্য ভিউ মডেলগুলি এই শ্রেণি থেকে উত্তরাধিকারী হও, যেমন:

বেস ভিউমোডেল

public class BaseViewModel
{
    public bool IsAdmin { get; set; }

    public BaseViewModel(IUserService userService)
    {
        IsAdmin = userService.IsAdmin;
    }
}

নির্দিষ্ট ভিউমোডেল দেখুন

public class WidgetViewModel : BaseViewModel
{
    public string WidgetName { get; set;}
}

এখন দেখুন কোডটি ভিউটিতে সরাসরি সম্পত্তি অ্যাক্সেস করতে পারে

<p>Is Admin: @Model.IsAdmin</p>

2

আমি নিম্নলিখিত পদ্ধতির সর্বাধিক দক্ষ হিসাবে খুঁজে পেয়েছি এবং _ ভিউস্টার্ট.চটিএমএল ফাইল এবং শর্তসাপূর্ণ বিবৃতি যখন প্রয়োজনবোধে ব্যবহার করে দুর্দান্ত নিয়ন্ত্রণ প্রদান করি:

_ ভিউস্টার্ট :

@{
 Layout = "~/Views/Shared/_Layout.cshtml";

 var CurrentView = ViewContext.Controller.ValueProvider.GetValue("controller").RawValue.ToString();

 if (CurrentView == "ViewA" || CurrentView == "ViewB" || CurrentView == "ViewC")
    {
      PageData["Profile"] = db.GetUserAccessProfile();
    }
}

ভিএ :

@{
   var UserProfile= PageData["Profile"] as List<string>;
 }

দ্রষ্টব্য :

পেজডেটা ভিউজে পুরোপুরি কাজ করবে; তবে, একটি আংশিকভিউয়ের ক্ষেত্রে এটি ভিউ থেকে শিশু আংশিকের কাছে যেতে হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.