एक दृश्य में कई मॉडल


302

मैं एक दृश्य में 2 मॉडल रखना चाहता हूं। पृष्ठ में LoginViewModelऔर दोनों हैं RegisterViewModel

जैसे

public class LoginViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class RegisterViewModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

क्या मुझे एक और ViewModel बनाने की आवश्यकता है जो इन 2 ViewModels को रखती है?

public BigViewModel
{
    public LoginViewModel LoginViewModel{get; set;}
    public RegisterViewModel RegisterViewModel {get; set;}
}

मुझे दृश्य को आगे लाने के लिए सत्यापन विशेषताओं की आवश्यकता है। यही कारण है कि मुझे ViewModels की आवश्यकता है।

क्या कोई दूसरा तरीका नहीं है जैसे (बिना BigViewModel):

 @model ViewModel.RegisterViewModel
 @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
 {
        @Html.TextBoxFor(model => model.Name)
        @Html.TextBoxFor(model => model.Email)
        @Html.PasswordFor(model => model.Password)
 }

 @model ViewModel.LoginViewModel
 @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
 {
        @Html.TextBoxFor(model => model.Email)
        @Html.PasswordFor(model => model.Password)
 }

3
इसे देखें: codeproject.com/Articles/687061/…
S.Serpooshan

1
@saeed serpooshan, विभिन्न विकल्पों के साथ लिंक के लिए बहुत बहुत धन्यवाद, 4 साल के बाद आपने एक टिप्पणी पोस्ट की और इससे मुझे मदद मिली, मैं सिर्फ ViewBagदृश्य में प्रत्येक के लिए इस्तेमाल किया , महान काम करता है
shaijut

@stom Just a FYI: पोस्ट लेखक को हमेशा एक सूचना मिलती है, लेकिन अगर आप किसी और को सूचित करना चाहते हैं, तो आपको @उनके नाम के सामने रखने की आवश्यकता है , जैसा कि मैंने यहां किया था।
jpaugh

जवाबों:


260

बहुत सारे तरीके हैं ...

  1. अपने BigViewModel के साथ आप करते हैं:

    @model BigViewModel    
    @using(Html.BeginForm()) {
        @Html.EditorFor(o => o.LoginViewModel.Email)
        ...
    }
  2. आप 2 अतिरिक्त दृश्य बना सकते हैं

    Login.cshtml

    @model ViewModel.LoginViewModel
    @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
    {
        @Html.TextBoxFor(model => model.Email)
        @Html.PasswordFor(model => model.Password)
    }

    और register.cshtml एक ही बात

    निर्माण के बाद आपको उन्हें मुख्य दृश्य में प्रस्तुत करना होगा और उन्हें viewmodel / viewdata पास करना होगा

    तो यह इस तरह हो सकता है:

    @{Html.RenderPartial("login", ViewBag.Login);}
    @{Html.RenderPartial("register", ViewBag.Register);}

    या

    @{Html.RenderPartial("login", Model.LoginViewModel)}
    @{Html.RenderPartial("register", Model.RegisterViewModel)}
  3. अपने वेब-साइट के अजाक्स भागों का उपयोग करना अधिक स्वतंत्र हो जाता है

  4. iframes, लेकिन शायद यह मामला नहीं है


2
क्या यह एक समस्या है यदि 2 टेक्स्टबॉक्स में आंशिक नाम का उपयोग करने के कारण फॉर्म पर एक ही नाम है?
शॉन मैक्लेन

2
नहीं, ठीक होना चाहिए- फायरबग (फ़ायरफ़ॉक्स पर) जैसी किसी चीज़ का उपयोग करने वाले तत्व पर स्वयं क्लिक करें और आपको आईडी = "LoginViewModel_Email" नाम = "LoginViewModel.Email" जैसा कुछ दिखाई देगा, इसलिए वास्तविक रूप में वे अद्वितीय हैं! एक दृश्य मॉडल वह होना चाहिए जो आपको चाहिए, बस प्रत्येक पृष्ठ को एक अलग URL पर पोस्ट करें और आपको ठीक होना चाहिए
हारून

@ लोल कोडर वास्तव में यह 2 रूप होंगे, प्रत्येक दृश्यदर्शी के लिए एक, लेकिन वैसे भी यदि आपके पास एक ही नाम के साथ 2 या 3 या अधिक होगा, तो आपको सर्वर साइड पर उस नाम के साथ एक सरणी मिलेगी (यदि आप इसे परम में डालते हैं पोस्ट एक्शन विधि)
ओमू

@Chuck Norris मैं asp.net mvc 4 का उपयोग कर रहा हूं और अपनी आंशिक दृश्य तकनीक लागू की है, लेकिन @Html.RenderActionएक त्रुटि की रिपोर्ट कर रहा है कि अभिव्यक्ति को एक मूल्य वापस करना होगा
Deptechtons

1
क्या आप बता सकते हैं कि यह कैसे काम करता है? मैं समझता हूं कि यह समस्या का समाधान है, लेकिन मैं इसका कोई मतलब नहीं निकाल सकता। मेरे पास इस समस्या का एक समान (थोड़ा अलग) उदाहरण है और मैं समझ नहीं पा रहा हूं कि इसे कैसे प्राप्त किया जाए।
आंद्रे

127

मैं इसका उपयोग करने की सलाह देता हूं Html.RenderActionऔर इसे पूरा करने के लिए PartialViewResults; यह आपको समान डेटा प्रदर्शित करने की अनुमति देगा, लेकिन प्रत्येक आंशिक दृश्य में अभी भी एक ही दृश्य मॉडल होगा और एक की आवश्यकता को हटा देगाBigViewModel

तो आपके विचार में निम्नलिखित जैसे कुछ हैं:

@Html.RenderAction("Login")
@Html.RenderAction("Register")

आपके नियंत्रक में कहां Loginऔर Registerदोनों क्रियाएं निम्नलिखित के रूप में परिभाषित की गई हैं:

public PartialViewResult Login( )
{
    return PartialView( "Login", new LoginViewModel() );
}

public PartialViewResult Register( )
{
    return PartialView( "Register", new RegisterViewModel() );
}

Loginऔर Registerतब, या साझा फ़ोल्डर में या तो वर्तमान दृश्य फ़ोल्डर में रहने वाले उपयोगकर्ता नियंत्रण हो सकता है और कुछ इस तरह करना चाहते हैं:

/Views/Saring/Login.cshtml: (या /Views/MyView/Login.cshtml)

@model LoginViewModel
@using (Html.BeginForm("Login", "Auth", FormMethod.Post))
{
    @Html.TextBoxFor(model => model.Email)
    @Html.PasswordFor(model => model.Password)
}

/Views / साझा करें /Register.cshtml: ((/Views/MyView/Register.cshtml)

@model ViewModel.RegisterViewModel
@using (Html.BeginForm("Login", "Auth", FormMethod.Post))
{
    @Html.TextBoxFor(model => model.Name)
    @Html.TextBoxFor(model => model.Email)
    @Html.PasswordFor(model => model.Password)
}

और आपके पास प्रत्येक कार्रवाई के लिए एक एकल नियंत्रक क्रिया, दृश्य और दृश्य फ़ाइल है, जो पूरी तरह से अलग है और किसी भी चीज़ के लिए एक दूसरे पर निर्भर नहीं है।


4
यह डिजाइनिंग के मामले में बहुत मायने रखता है, लेकिन दक्षता के मामले में, क्या इसे mvc चक्र के 3 पूर्ण चक्रों से गुजरना नहीं है? stackoverflow.com/questions/719027/renderaction-renderpartial/…
Shawn Mclean

6
हां, आप सही हैं: यह प्रत्येक के लिए एक अतिरिक्त पूर्ण MVC चक्र का कारण बनता है RenderAction। मैं हमेशा वायदा पैक के अपने हिस्से को भूल जाता हूं क्योंकि मेरी परियोजना में हमेशा डिफ़ॉल्ट रूप से वह डीएल शामिल होता है। यह वास्तव में वरीयता और आवेदन की आवश्यकताओं पर निर्भर करता है जैसे कि अतिरिक्त पीवीसी चक्रों को अलग करने के लायक है जो यह डिजाइन पक्ष पर देता है। बहुत बार आप RenderActionपरिणामों को कैश कर सकते हैं इसलिए केवल हिट जो आप लेते हैं वह नियंत्रक कारखाने के माध्यम से थोड़ी अतिरिक्त प्रसंस्करण है।
द राईटहॉयस

मैंने ऊपर लागू किया है .. मुझे क्या याद आ रहा है? कृपया मदद करें: stackoverflow.com/questions/9677818/…
diegohb

बकवास! इसने मेरे लिए गेट के ठीक बाहर काम किया। मैं केवल एक युगल उपयोगकर्ताओं के साथ एक आंतरिक साइट बना रहा हूं ... इसलिए दक्षता मेरी वास्तविक चिंता नहीं है। धन्यवाद!
डेरेक एवरमोर

1
PartialView को काम करने के लिए घुंघराले कोष्ठक का उपयोग करना पड़ा।
null

113

एक और तरीका है:

@model Tuple<LoginViewModel,RegisterViewModel>

मैंने समझाया है कि इस पद्धति का उपयोग दूसरे दृश्य के लिए नियंत्रक और नियंत्रक दोनों में कैसे किया जाए: ASP MVC 3 में एक दृश्य में दो मॉडल

आपके मामले में आप निम्नलिखित कोड का उपयोग करके इसे लागू कर सकते हैं:

दृश्य में:

@using YourProjectNamespace.Models;
@model Tuple<LoginViewModel,RegisterViewModel>

@using (Html.BeginForm("Login1", "Auth", FormMethod.Post))
{
        @Html.TextBoxFor(tuple => tuple.Item2.Name, new {@Name="Name"})
        @Html.TextBoxFor(tuple => tuple.Item2.Email, new {@Name="Email"})
        @Html.PasswordFor(tuple => tuple.Item2.Password, new {@Name="Password"})
}

@using (Html.BeginForm("Login2", "Auth", FormMethod.Post))
{
        @Html.TextBoxFor(tuple => tuple.Item1.Email, new {@Name="Email"})
        @Html.PasswordFor(tuple => tuple.Item1.Password, new {@Name="Password"})
}

ध्यान दें कि मैंने फॉर्म बनाते समय प्रत्येक गुण के लिए नाम विशेषताओं को मैन्युअल रूप से बदल दिया है। इसे करने की आवश्यकता है, अन्यथा यह प्रसंस्करण के लिए संबंधित विधि के लिए मान भेजे जाने पर टाइप मॉडल के विधि पैरामीटर के लिए ठीक से मैप नहीं किया जाएगा। मैं इन रूपों को अलग-अलग संसाधित करने के लिए अलग-अलग तरीकों का उपयोग करने का सुझाव दूंगा, इस उदाहरण के लिए मैंने Login1 और Login2 विधियों का उपयोग किया। Login1 विधि में RegisterViewModel प्रकार का पैरामीटर होना आवश्यक है और Login2 के लिए LoginViewModel प्रकार का पैरामीटर आवश्यक है।

यदि एक्शनलिंक आवश्यक है तो आप उपयोग कर सकते हैं:

@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id })

देखने के लिए नियंत्रक की विधि में, टुपल के एक प्रकार को बनाने और फिर दृश्य में पास करने की आवश्यकता होती है।

उदाहरण:

public ActionResult Details()
{
    var tuple = new Tuple<LoginViewModel, RegisterViewModel>(new LoginViewModel(),new RegisterViewModel());
    return View(tuple);
}

या आप LoginViewModel और RegisterViewModel के दो उदाहरण मानों के साथ भर सकते हैं और फिर इसे दृश्य में पास कर सकते हैं।


यह इसे संभालने का एक शानदार तरीका था, धन्यवाद! मुझे जो चाहिए था वो किया।
टॉड डेविस

मैंने यह कोशिश की है, लेकिन अगर मैं उपयोग करता हूं EditorForया HiddenFor(जो कि आदर्श रूप से मैं क्या उपयोग करना चाहता हूं) मॉडल गुणों को तब सेट नहीं किया जाता है जब Login1/ Login2नियंत्रक विधियों को बुलाया जाता है। संभवतः @Name=मानचित्रण को अनदेखा किया जा रहा है। क्या HiddenForइस स्थिति के लिए कुछ अन्य चाल की आवश्यकता है?
गैरी चैपमैन

1
यह बिल्कुल भी काम नहीं करेगा - जब आप फॉर्म जमा करते हैं तो आप मॉडल से

@ हामिद थैंक्स हामिद, एमवीसी में नौसिखिया के लिए, यह मेरे लिए सबसे सरल जवाब था। धन्यवाद।
हेरोल्ड_फिंच

फॉर्म जमा करते समय आपने मॉडल को कैसे बांधा था?
मोहम्मद नौरेलिन

28

एक दृश्य मॉडल का उपयोग करें जिसमें कई दृश्य मॉडल हैं:

   namespace MyProject.Web.ViewModels
   {
      public class UserViewModel
      {
          public UserDto User { get; set; }
          public ProductDto Product { get; set; }
          public AddressDto Address { get; set; }
      }
   }

आपके विचार में:

  @model MyProject.Web.ViewModels.UserViewModel

  @Html.LabelFor(model => model.User.UserName)
  @Html.LabelFor(model => model.Product.ProductName)
  @Html.LabelFor(model => model.Address.StreetName)

1
यह एक महान समाधान है, और मॉडल सत्यापन अभी भी बिना किसी योग्यता के काम करता है। धन्यवाद!
AFM-क्षितिज

11

क्या मुझे एक और दृश्य बनाने की आवश्यकता है जो इन 2 विचारों को रखता है?

उत्तर: नहीं

क्या कोई दूसरा तरीका नहीं है जैसे कि (BigViewModel के बिना):

हां , आप Tuple का उपयोग कर सकते हैं (कई मॉडल को ध्यान में रखते हुए जादू लाता है)।

कोड:

 @model Tuple<LoginViewModel, RegisterViewModel>


    @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
    {
     @Html.TextBoxFor(tuple=> tuple.Item.Name)
     @Html.TextBoxFor(tuple=> tuple.Item.Email)
     @Html.PasswordFor(tuple=> tuple.Item.Password)
    }


    @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
     {
      @Html.TextBoxFor(tuple=> tuple.Item1.Email)
      @Html.PasswordFor(tuple=> tuple.Item1.Password)
     }

क्या यह उस नियंत्रक के लिए ठीक से मैप नहीं होगा जो फॉर्म स्वीकार कर रहा था? मैंने सोचा था कि यह "नाम" की तलाश करने से पहले आपके मामले में "आइटम" की तलाश करेगा।
सॉलिडस्नेक4444

7

इस ModelCollection.cs को अपने मॉडल में जोड़ें

using System;
using System.Collections.Generic;

namespace ModelContainer
{
  public class ModelCollection
  {
   private Dictionary<Type, object> models = new Dictionary<Type, object>();

   public void AddModel<T>(T t)
   {
      models.Add(t.GetType(), t);
   }

   public T GetModel<T>()
   {
     return (T)models[typeof(T)];
   }
 }
}

नियंत्रक:

public class SampleController : Controller
{
  public ActionResult Index()
  {
    var model1 = new Model1();
    var model2 = new Model2();
    var model3 = new Model3();

    // Do something

    var modelCollection = new ModelCollection();
    modelCollection.AddModel(model1);
    modelCollection.AddModel(model2);
    modelCollection.AddModel(model3);
    return View(modelCollection);
  }
}

देखें:

enter code here
@using Models
@model ModelCollection

@{
  ViewBag.Title = "Model1: " + ((Model.GetModel<Model1>()).Name);
}

<h2>Model2: @((Model.GetModel<Model2>()).Number</h2>

@((Model.GetModel<Model3>()).SomeProperty

मुझे यह दृष्टिकोण पसंद है क्योंकि यह मुझे एक ही दृश्य में अलग-अलग मॉडल का उपयोग करने की अनुमति देता है बिना उन्हें प्रतिच्छेद किए बिना।
मैट स्मॉल

6

ऐसा करने का एक सरल तरीका

हम सभी मॉडल को पहले कॉल कर सकते हैं

@using project.Models

फिर अपने मॉडल को व्यूबैग के साथ भेजें

// for list
ViewBag.Name = db.YourModel.ToList();

// for one
ViewBag.Name = db.YourModel.Find(id);

और देखने में

// for list
List<YourModel> Name = (List<YourModel>)ViewBag.Name ;

//for one
YourModel Name = (YourModel)ViewBag.Name ;

फिर आसानी से मॉडल की तरह इस का उपयोग करें


3

मेरी सलाह है कि एक बड़ा दृश्य मॉडल बनाएं:

public BigViewModel
{
    public LoginViewModel LoginViewModel{get; set;}
    public RegisterViewModel RegisterViewModel {get; set;}
}

अपने Index.cshtml में, यदि उदाहरण के लिए आपके पास 2 भाग हैं:

@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers
@model .BigViewModel

@await Html.PartialAsync("_LoginViewPartial", Model.LoginViewModel)

@await Html.PartialAsync("_RegisterViewPartial ", Model.RegisterViewModel )

और नियंत्रक में:

model=new BigViewModel();
model.LoginViewModel=new LoginViewModel();
model.RegisterViewModel=new RegisterViewModel(); 

2

मैं कहना चाहता हूं कि मेरा समाधान इस स्टैकओवरफ्लो पेज पर दिए गए जवाब की तरह था: ASP.NET MVC 4, एक दृश्य में कई मॉडल?

हालाँकि, मेरे मामले में, उनके नियंत्रक में उपयोग की जाने वाली linq क्वेरी ने मेरे लिए काम नहीं किया।

यह कहा जाता है क्वेरी:

var viewModels = 
        (from e in db.Engineers
         select new MyViewModel
         {
             Engineer = e,
             Elements = e.Elements,
         })
        .ToList();

नतीजतन, "आपके विचार में यह निर्दिष्ट करें कि आप दृश्य मॉडल के संग्रह का उपयोग कर रहे हैं" मेरे लिए भी काम नहीं किया।

हालांकि, उस समाधान पर थोड़ी भिन्नता ने मेरे लिए काम किया। यहाँ मेरा समाधान है अगर यह किसी को भी मदद करता है।

यहाँ मेरा विचार मॉडल है जिसमें मुझे पता है कि मेरे पास सिर्फ एक टीम होगी लेकिन उस टीम में कई बोर्ड हो सकते हैं (और मेरे मॉडल फ़ोल्डर btw के भीतर एक ViewModels फ़ोल्डर है, इसलिए नामस्थान):

namespace TaskBoard.Models.ViewModels
{
    public class TeamBoards
    {
        public Team Team { get; set; }
        public List<Board> Boards { get; set; }
    }
}

अब यह मेरा नियंत्रक है। उपरोक्त संदर्भित लिंक में समाधान से यह सबसे महत्वपूर्ण अंतर है। मैं अलग तरीके से दृश्य भेजने के लिए ViewModel का निर्माण करता हूं।

public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            TeamBoards teamBoards = new TeamBoards();
            teamBoards.Boards = (from b in db.Boards
                                 where b.TeamId == id
                                 select b).ToList();
            teamBoards.Team = (from t in db.Teams
                               where t.TeamId == id
                               select t).FirstOrDefault();

            if (teamBoards == null)
            {
                return HttpNotFound();
            }
            return View(teamBoards);
        }

तब मेरे विचार में मैं इसे एक सूची के रूप में निर्दिष्ट नहीं करता। मैं सिर्फ "@model TaskBoard.Models.ViewModels.TeamBoards" करता हूं, तब मुझे टीम के बोर्डों पर पुनरावृति करने के लिए केवल प्रत्येक की आवश्यकता होती है। यहाँ मेरा विचार है:

@model TaskBoard.Models.ViewModels.TeamBoards

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>Team</h4>
    <hr />


    @Html.ActionLink("Create New Board", "Create", "Board", new { TeamId = @Model.Team.TeamId}, null)
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => Model.Team.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => Model.Team.Name)
            <ul>
                @foreach(var board in Model.Boards)
                { 
                    <li>@Html.DisplayFor(model => board.BoardName)</li>
                }
            </ul>
        </dd>

    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Team.TeamId }) |
    @Html.ActionLink("Back to List", "Index")
</p>

मैं ASP.NET MVC के लिए काफी नया हूं इसलिए मुझे यह पता लगाने में थोड़ा समय लगा। इसलिए, मुझे उम्मीद है कि यह पोस्ट किसी व्यक्ति को कम समय में अपनी परियोजना के लिए यह पता लगाने में मदद करेगी। :-)



1
  1. अपने मॉडल में एक नया वर्ग और के गुणों बनाएं LoginViewModelऔर RegisterViewModel:

    public class UserDefinedModel() 
    {
        property a1 as LoginViewModel 
        property a2 as RegisterViewModel 
    }
  2. फिर UserDefinedModelअपने विचार में उपयोग करें।


1
हाँ, यह मेरे लिए काम करता है। तब मैंने इसे इस तरह संदर्भित किया: (मॉडल को देखने के शीर्ष पर घोषित किया गया था। इसके अंदर 2 मॉडल थे: प्रोफ़ाइल, और ईमेलस्टाफ।।। @ Html.DisplayNameFor (मॉडल => model.profile.BlackoutBegin) में। नियंत्रक मैंने नीचे दिए गए @notso पोस्ट का उपयोग करते हुए एक मॉडल को भरा। मुझे अन्य becuase को भरने की आवश्यकता नहीं थी मैं इसे केवल एक इनपुट के लिए उपयोग कर रहा था।
JustJohn

0

यह IEnumerable के साथ एक सरल उदाहरण है।

मैं दृश्य पर दो मॉडल का उपयोग कर रहा था: खोज मापदंड (SearchParams मॉडल) के साथ एक रूप, और परिणामों के लिए एक ग्रिड, और मैं IEnumerable मॉडल और उसी मॉडल पर अन्य मॉडल को जोड़ने के तरीके से जूझ रहा था। यहाँ मैं क्या लेकर आया हूँ, आशा है कि इससे किसी को मदद मिलेगी:

@using DelegatePortal.ViewModels;

@model SearchViewModel

@using (Html.BeginForm("Search", "Delegate", FormMethod.Post))
{

                Employee First Name
                @Html.EditorFor(model => model.SearchParams.FirstName,
new { htmlAttributes = new { @class = "form-control form-control-sm " } })

                <input type="submit" id="getResults" value="SEARCH" class="btn btn-primary btn-lg btn-block" />

}
<br />
    @(Html
        .Grid(Model.Delegates)
        .Build(columns =>
        {
            columns.Add(model => model.Id).Titled("Id").Css("collapse");
            columns.Add(model => model.LastName).Titled("Last Name");
            columns.Add(model => model.FirstName).Titled("First Name");
        })

...)

SearchViewModel.cs:

namespace DelegatePortal.ViewModels
{
    public class SearchViewModel
    {
        public IEnumerable<DelegatePortal.Models.DelegateView> Delegates { get; set; }

        public SearchParamsViewModel SearchParams { get; set; }
....

DelegateController.cs:

// GET: /Delegate/Search
    public ActionResult Search(String firstName)
    {
        SearchViewModel model = new SearchViewModel();
        model.Delegates = db.Set<DelegateView>();
        return View(model);
    }

    // POST: /Delegate/Search
    [HttpPost]
    public ActionResult Search(SearchParamsViewModel searchParams)
    {
        String firstName = searchParams.FirstName;
        SearchViewModel model = new SearchViewModel();

        if (firstName != null)
            model.Delegates = db.Set<DelegateView>().Where(x => x.FirstName == firstName);

        return View(model);
    }

SearchParamsViewModel.cs:

namespace DelegatePortal.ViewModels
{
    public class SearchParamsViewModel
    {
        public string FirstName { get; set; }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.