0

i have a problem about MVC, but first I am sorry for my english :D . Now i am trying to make a form for users and i have a critical issue when i want connect to values with database.

My Form is like this : https://i.hizliresim.com/vJ6r2p.png

Models :

[Table("Testers")]
    public class Testers
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }

        [StringLength(50),Required]
        public string testerName { get; set; }

        public ICollection<Scores> Scores { get; set; }
    }
    [Table("Technologies")]
        public class Technologies
        {
            [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public int ID { get; set; }
            [StringLength(50)]
            public string technologyName { get; set; }
            [StringLength(50)]
            public string type { get; set; }
        }
    [Table("Scores")]
    public class Scores
    {
        [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        [DefaultValue(0)]
        public int score { get; set; }

        public virtual Testers tester { get; set; }
        public virtual Technologies technology { get; set; }
    }

ViewModels:

  public class TechnologiesView
    {
        public List<Technologies> Technologies { get; set; }
        public Scores Scores { get; set; }
    }

Controller :

public ActionResult Page2()
        {
            TechnologiesView allTechs = new TechnologiesView();
            allTechs.Technologies = db.Technologies.ToList();
            return View(allTechs);
        }

View:

@model TechnologiesView
@{
    ViewBag.Title = "Page2";
}
<style>
    #lang {
        font-size: 15px;
        color: gray;
    }

    #tech {
        font-size: 13px;
        color: gray;
    }
</style>

<div class="container">
    <div class="row col-xs-12 bilgi" style="color:black">
        @HelperMethods.Title("Kendini Skorla!")
        <br />
        <i>Bilgi Düzeyini 0 ile 5 puan arasında notlar mısın? (0=Hiç 5= İleri Seviye)</i>
    </div>
</div>

<hr />
@using (Html.BeginForm())
{
    <div class="container-fluid" style="padding-left:50px; margin:0px">
        <div class="row" id="lang">

            @foreach (Technologies techs in Model.Technologies)
            {
                if (techs.type == "lang")
                {
                    <div class="col-md-1 col-sm-2 col-xs-6">
                        @(techs.technologyName)
                    </div>
                    <div class="col-md-1 col-sm-2 col-xs-6">
                        (@(Html.TextBoxFor(x => x.Scores.score, new
                     {
                         id = techs.ID,
                         name = "techID",
                         style = "display:inline; width:20px; height:20px; font-size:smaller; padding:0px; text-align:center",
                         @class = "form-control"
                     })))
                    </div>
                }
            }
        </div>
        <hr style="color:black" />
        <div class="row" id="tech">
            @foreach (Technologies techs in Model.Technologies)
            {
                if (techs.type == "tech")
                {
                    <div class="col-md-1 col-sm-2 col-xs-6" id="tech">
                        @(techs.technologyName)
                    </div>
                    <div class="col-md-1 col-sm-2 col-xs-6">
                        @Html.HiddenFor(x=>techs.ID)
                        (@(Html.TextBoxFor(x => x.Scores.score, new
                     {
                         id = techs.ID,
                         name = "techID",
                         style = "display:inline; width:20px; height:20px; font-size:smaller; padding:0px; text-align:center",
                         @class = "form-control"
                     })))
                    </div>
                }
            }
        </div>
        <hr />
        <div class="row col-xs-12" id="lang">
            <span>Kullandığınız IDE’ler (yazınız)</span>
            <br />
            <div style="margin-bottom:10px; text-align:center">
                @HelperMethods.TextArea("Ide", 3)
            </div>
        </div>
        <div style="text-align:right; margin-bottom:10px">
            @HelperMethods.Button("btnPage2")
        </div>
    </div>
}

Now user has to give a score to him/herself for every technologies or languages and after this i want to when user click to button "Follow the next page(it's turkish)" i will select the last saved user from maxID value in Testers and i have to connect scores with technologies and testers but i don't know how can i get textboxes' values and which technology's value is this value on post :D

Kadir Kalkan
  • 248
  • 2
  • 10
  • What are you trying to edit here? Your view makes no sense at all and wont bind to anything related to your model. Under no circustances do you ever change the `name` attribute when using `HtmlHelper` methods to generate form controls. –  Nov 05 '17 at 06:26
  • And you cannot use a `foreach` loop to generate form controls for collection items (refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) for an explanation) –  Nov 05 '17 at 06:28
  • i want to take many value from user for each technology and i will save them to database as Scor for example: user1's Css Ability is 3 point – Kadir Kalkan Nov 05 '17 at 06:37
  • So you want the user to enter a score for each technology? And there a 2 different types of technologies (tech and lang)? –  Nov 05 '17 at 06:39
  • yes i am looking for 10 hour but i couldn't find any thing i can't match values if it would be C# form i can make it very easy but web's nature is different for me :D – Kadir Kalkan Nov 05 '17 at 06:47
  • Then everything your doing is wrong. And what is `@HelperMethods.Button("btnPage2")`? Is that a submit button and what is the method your posting the form to? –  Nov 05 '17 at 06:50
  • button is submit i didn't write post method yet because i don't know how i can get values form form to controller as view class – Kadir Kalkan Nov 05 '17 at 06:53
  • There is so much wrong with your code it will take a while to explain and show how to do this correctly. No time just now but will add an answer in a hour or 2. –  Nov 05 '17 at 06:58
  • this is the project if u want look. https://bitbucket.org/kadirkalkan/workcubeformmvc/overview – Kadir Kalkan Nov 05 '17 at 06:58
  • thank you so much if someone want from me anything without knowledge in a short time i am trying to make it but i can't learn what is wrong or not completely – Kadir Kalkan Nov 05 '17 at 07:01
  • As a side note, I just had a quick look at your project. You must absolutely delete all those `@HelperMethods` from your project - ALWAYS use the `HtmlHelper` methods to generate form controls –  Nov 05 '17 at 08:21
  • And your note in the question that _i will select the last saved user from maxID value in Testers_ is definitely not the correct approach (but its not clear what your wanting to do there) –  Nov 05 '17 at 08:25

1 Answers1

1

You generating form controls which have no relationship at all to your model (which is also wrong anyway). Never attempt to change the name attribute when using the HtmlHelper methods (and there is no reason to change the id attribute either)

Next, you cannot use a foreach loop to generate form controls for a collection. You need a for loop or EditorTemplate to generate the correct name attributes with indexers. Refer this answer for a detailed explanation.

Then you cannot use a if block inside the loop (unless you include a hidden input for the collection indexer), because by default the DefaultModelBinder required collection indexers to start at zero and be consecutive.

First start by creating view models to represent what your want to display/edit in the view.

public class ScoreVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Score { get; set; }
}
public class TechnologiesVM
{
    public List<ScoreVM> Languages { get; set; }
    public List<ScoreVM> Technologies { get; set; }
    public string Notes { get; set; } // for your textarea control
}

Note you will probably want to add validation attributes such as a [Range] attribute for the Score property

In the GET method, initialize and populate your view model and pass it to the view

public ActionResult Page2()
{
    IEnumerable<Technologies> technologies = db.Technologies;
    TechnologiesVM model = new TechnologiesVM
    {
        Languages = technologies.Where(x => x.type == "lang")
            .Select(x => new ScoreVM{ ID = x.ID, Name = x.technologyName }).ToList(),
        Technologies = technologies.Where(x => x.type == "tech")
            .Select(x => new ScoreVM{ ID = x.ID, Name = x.technologyName }).ToList(),
    };
    return View(model);
}

and in the view

@model TechnologiesVM
....
@using (Html.BeginForm())
{
    ....
    @for (int i = 0; i < Model.Languages.Count; i++)
    {
        @Html.HiddenFor(m => m.Languages[i].ID)
        @Html.HiddenFor(m => m.Languages[i].Name)
        @Html.LabelFor(m => m.Languages[i].Score, Model.Languages[i].Name)
        @Html.TextBoxFor(m => m.Languages[i].Score)
        @Html.ValidationMessageFor(m => m.Languages[i].Score)
    }
    @for (int i = 0; i < Model.Languages.Count; i++)
    {
        .... // repeat above
    }
    @Html.LabelFor(m => m.Notes)
    @Html.TextAreaFor(m => m.Notes)
    @Html.ValidationMessageFor(m => m.Notes)

    <input type="submit" />
}

and the POST method will be

public ActionResult Page2(TechnologiesVM model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    ... // save the data and redirect
}
  • ' public class Technologies { public int ID { get; set; } public string technologyName { get; set; } public string type { get; set; } }' my technologies class is like this and when try to create model with List = Linq --> it's giving cast error – Kadir Kalkan Nov 05 '17 at 08:52
  • Languages = (List)technologies.Where(x => x.type == "lang") .Select(x => new ScoreVM { ID = x.ID, Name = x.technologyName }) i cast it like this is it true ? because it gave same exception and by the way thank you very much for your help – Kadir Kalkan Nov 05 '17 at 08:58
  • my bad :( i forget to add .toList() :D – Kadir Kalkan Nov 05 '17 at 09:02