1

I want to get and Save ASP NET MVC Membership provider UserProfile table UserId field into a separate table?

Here is my model

public class Product
{
    public int ProductId { get; set; }
    public int UserId { get; set; }
    public string ProductName { get; set; }

}

I don't want to add UserId field into my Model anymore. and here is my controller:

private UsersContext db = new UsersContext();
// GET: /ProCont/
int UserID = (int)Membership.GetUser().ProviderUserKey;
public ActionResult Index()
{
    return View(db.Products.Where(p => p.UserId == UserID).ToList());
}

What to do?

Regards Dostdar

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
  • @Rahul, I have a product table where the users can enter their product the problem i faced was that when a user logged on he/she could see all users Product. i wanted to prevent that then i add a UserId in my model class and then used a where class in my controller class to prevent other users to view the other user products. now when i create a product i have to put the UserId for each product entry and that is a headache. i don't want that instead i want to this automatically when a user logged in and wants to create a product the user id should automatically get and save to database. –  Dec 31 '15 at 20:56
  • What you have currently is the right way to do it else there is no way you can relate a product with a specific user. This is what called as referential integrity. Here `userid` in your model class is acting as `FOREIGN KEY`. You just can't do it automatically. – Rahul Dec 31 '15 at 21:01
  • @rahul how? tell me more as far as i am newbie to the MVC? –  Dec 31 '15 at 21:07
  • It's not about MVC rather about DB concept. At the end those Model going to represent DB entities and so, if you don't have userid in products table then try relating a product to a user and see if you can do so. That will give you an idea what I am saying. – Rahul Dec 31 '15 at 21:10
  • Okay @Rahul i will let this UserId in my Model class but what i am not clear about is how to save this UserId automatically when a user wants to create a Product? I couldn't get your code? –  Dec 31 '15 at 21:14
  • I Have this in product create method, how would you edit this? @Rahul public ActionResult Create(Product product) { if (ModelState.IsValid) { db.Products.Add(product); db.SaveChanges(); return RedirectToAction("Index"); } return View(product); } –  Dec 31 '15 at 21:17
  • Give a moment .... check answer after some time. – Rahul Dec 31 '15 at 21:18
  • @PetterFriberg I don't know how to do it in Comment. –  Dec 31 '15 at 21:39
  • @NaserDostdar it was my edit review, I was only formatting your post some, sorry for the minimal description...., however instead of using comment to improve your post, consider editing it.... – Petter Friberg Dec 31 '15 at 21:40
  • @NaserDostdar, I have added a separate answer with code fragment to show you how to add it. Check it. – Rahul Jan 01 '16 at 05:31
  • @PetterFriberg No worries, Sure it is a good point i'll do it in my next question :) –  Jan 01 '16 at 10:52

2 Answers2

1

Disclaimer: It will be too long as a edit in already existing answer and hence posted in separate answer.

To answer your question on how will you add the UserID field in your model object below is a detailed description with code segment.

Considering that you have already added Products entity using ADO.NET Entity Data Model. Add a separate class file to your Models folder with any name you like and have the below code. Below code segment decorate your model object.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel;

namespace MvcApplication1.Models
{
    [MetadataType(typeof(productMetadata))]
    public partial class Product
    {

    }

    public class productMetadata
    {
        [HiddenInput(DisplayValue = false)]
        public int ProductId { get; set; }

        // to make the field hidden and will not display in browser
        [HiddenInput(DisplayValue = false)]
        //directing that don't scaffold this column since it will be added manually
        [ScaffoldColumn(false)]
        public int UserId { get; set; }
    }
}

You can directly modify the auto-generated Product class in EF but if you re-generate the EF model again then the changes will be gone. So, above shown approach is best using MetadataType attribute.

Controller Action Method(s):

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Create()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Create([Bind(Include = "ProductName, ProductId")]Product product) 
    {
        SampleContext db = new SampleContext();

        if (ModelState.IsValid) 
        {
            product.UserId = (int)Membership.GetUser().ProviderUserKey;
            db.Products.Add(product); 
            db.SaveChanges(); 
            return RedirectToAction("Index"); 
        } 

        return View(product); 
    }

    public ActionResult List()
    {
        SampleContext db = new SampleContext();
        IEnumerable<Product> products = db.Products.ToList();
        return View(products);
    }
}
}

View (Specifically the Create view):

@model MvcApplication1.Models.Product

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Product</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ProductName)
            @Html.ValidationMessageFor(model => model.ProductName)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Notice that the view has editable controls for only productname as input field since ProductID is an identity column and UserID getting value in code and not from user.

Rahul
  • 76,197
  • 13
  • 71
  • 125
  • there are no words to thank you with! What an answer to the point and simple. Thanks a lot just appreciate your efforts! –  Jan 01 '16 at 10:49
  • Would you please solve this question too? http://stackoverflow.com/questions/34535818/how-to-solve-unable-to-connect-to-sql-server-database –  Jan 02 '16 at 08:12
0

It's really not clear what you are asking here? But are you saying that you want to store the UserID into your Products table in database. Then you can designate your model class so like below

[System.ComponentModel.DataAnotations.Table("Products")]
public class Product
{
    public int ProductId { get; set; }
    public int UserId { get; set; }
    public string ProductName { get; set; }
}

Either you can create the table Products manually or you can use EF code first Migrations to create a snapshot and update the database in order to add the newly created table.

Then you can add data to your table like

Product p1 = new Product
{
  UserID = (int)Membership.GetUser().ProviderUserKey,
  ProductName = "XXX";
};

db.Products.Add(p1);
db.SaveChanges();

Per your comment:

What you have currently is the right way to do it else there is no way you can relate a product(s) with a specific user. This is what called as Referential Integrity Constraint. Here UserID in your model class is acting as FOREIGN KEY. You just can't do it automatically.

Rahul
  • 76,197
  • 13
  • 71
  • 125
  • I am Using EF Migrations how can i just add that UserId to my table i couldn't catch this @Rahul –  Dec 31 '15 at 21:12