0

I have simple input form (basically for feedback) with following fields: Name, Gender, Mobile-Number, Complaint text. (To simplify I am not mentioning any POST action OR submit button on the form)

Currently, I have created following MVC structure:

public class ComplaintController
{
    [HttpGet]
    public ActionResult Index()
    {
       return View(); //This view displays the complaint form with all above fields
    }
}

I read this and several other links where they suggest to use @Html.EditorFor as it creates UI based on model data-type.

Currently, I am not passing any model to the [HttpGet] view. If I want to use @Html.EditorFor, I need to pass my model to [HttpGet] Index View, how can I do that? What is best pratise to create such MVC forms?

Sahil Sharma
  • 3,847
  • 6
  • 48
  • 98
  • If you just want a output of what the user has submitted, there are lots of ways to do in MVC, if you wanted the confirmation message inside a new view with the saved fields, after your db.SaveChanges, you could do a return RedirectToAction("ComfirmationView",yourModel), then pass this to a ActionResult Comfirmation(YourModel yourModel) – Henry24 Jul 03 '17 at 19:46
  • I think you got confuse, i am rephrased the question. removed all the unnecessary details. please check – Sahil Sharma Jul 03 '17 at 19:50
  • you should use '@model YourModel', you add this code at the top of the view, or when you add the view there is an option create strongly typed view, check this and under model class choose your model class.. [read more](https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-3) – Munzer Jul 03 '17 at 21:47

3 Answers3

1

Your Controller:

    public ActionResult Index()
    {
        whateverModel d = new whateverModel();
        return View(d);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(whateverModel m)
    {

        if (ModelState.IsValid)
        {

           //its valid, update your database or do soemthing useful here
           return RedirectToAction("Success");
        }
        //its not valid reload the page and let data annotations show the error
        return View(m);
    }

Once you have your code in the controller then you can have visual studio auto-create your view. In your controller, right click the "d" in return View(d); and select "Add View." Change the Template to "create" and Model class to your Model (whateverModel in this example). It will auto generate the chtml page for you with the model imported and the editors already generated for you. Example auto generated view below. The you can work on styling and such.

cshtml:

    @model YourSolution.Models.whateverModel

    @{
        ViewBag.Title = "Whatever";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }

    <h2>Whatever</h2>

    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
            <h4>Whatever</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.FriendlyName, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.FriendlyName, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.FriendlyName, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Order, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Order, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Order, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
Travis Acton
  • 4,292
  • 2
  • 18
  • 30
  • This helps, but is it recommended practise to initialize such blank objects in httpget as you did in "View(d);". This would help to auto create the view as such but otherwise this is unnecessary allocation of memory as this model would never be used? – Sahil Sharma Jul 04 '17 at 03:41
  • It is recommend practice due to non-nullable types. Let's ignore the fact that most people are setting some value for a property in the model initial constructor. Let's say for simplicity sake you have a customer model that contains an int custID that you are using as a primary key in a DB. In the view you do not want to show the custID so you set it as a hidden field. Go ahead and initialize the model in your http get and watch it flow to your post on submit THEN remove the initialization and watch what happens in the post when you hit the "if(ModelState.IsValid)" line. – Travis Acton Jul 05 '17 at 17:38
  • That is not to say you cannot program around this to really fine tune your memory utilization, you just need to figure out if it is worth it or not as small simple objects do not take up much memory at all and large complex objects will most likely will have you initializing some properties in your constructor just for normal business logic. I guess what I am saying is just be aware. – Travis Acton Jul 05 '17 at 17:43
1

Currently, I am not passing any model to the [HttpGet] view. If I want to use @Html.EditorFor, I need to pass my model to [HttpGet] Index View, how can I do that?

Hi sahil ,As a first step , create one model class like below

public class FeedBack
{
   public string  Name{get;set;}
   public string  Gender{get;set;}
   public int  Mobile-Number{get;set;}
   public string  Complaint{get;set;}

  // other additional fields


}

And in the controller get method ,pass a model like below

public class ComplaintController
{
    [HttpGet]
    public ActionResult Index()
    {
      FeedBack OBJFeedback = new FeedBack();    
       return View(OBJFeedback); 
    }
}

And in a view , strongly type this model and post the data as you want to the controller post methods.

Here is the example of strongly typed view : http://www.c-sharpcorner.com/UploadFile/abhikumarvatsa/strongly-typed-views-in-mvc/

Important Note : In the get action method , since you dont want to display any values by default in the view , even if you dont pass model object it will work in the same way.

Hope the above information was useful

Thanks

Karthik

Karthik Elumalai
  • 1,574
  • 1
  • 11
  • 12
  • This helps, but is it recommended practise to initialize such blank objects in httpget as you did in "View(OBJFeedback);". This would help to auto create the view as such but otherwise this is unnecessary allocation of memory as this model would never be used? – Sahil Sharma Jul 04 '17 at 04:51
  • Yup you are perfectly right , that help to auto create the view , otherwise that was an unnecessary allocation of memory. so dont create model object in the httpget .thanks karthik – Karthik Elumalai Jul 04 '17 at 15:24
  • Great, but then how would i leverage the features of Html.Editorfor without any model? Any other way out? – Sahil Sharma Jul 04 '17 at 16:58
  • yes, you can put the model in the view without passing from the httpget method. that way you can utilize the features of all strongly typed html helper like editorfor and textboxfor. – Karthik Elumalai Jul 05 '17 at 01:15
0

If you want to use @Html.EditorFor, then you mast pass the model to the view.What does @Html.EditorFor do? It makes the html tag like

<input class="text-box single-line" id="Name" name="Name" type="text" value="">

So if you do not want to pass the model to the view then you need to write the raw html tag like above. It is important to keep the html tag's name property same as the mvc's model property because when you want to post the data to the controller the name property of the html tag will map the mvc model property and get the corresponding value at the Controller method.

At the view(somthing.cshtml) you can use html tags, because .cshtml==.cs+html . So the whole code look like

Controller methods

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



[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult FeedBack(FeedBackModel Model)
{
    var feedBack = Model;
     return View();
 }

And the View

<form action="/Home/FeedBack" method="post" id="feedBackForm">
    @Html.AntiForgeryToken()
    <hr>
    <div class="form-group">
        <div class="col-md-5">
            <label for="Name">Name</label>
        </div>
        <div class="col-md-5">
            <input class="text-box single-line" name="Name" type="text">
        </div>
        </div>
    <div class="form-group">
        <div class="col-md-5">
            <label for="Name">Gender</label>
        </div>
        <div class="col-md-5">
            <select name="Gender">
                <option value="male">Male</option>
                <option value="female">Female</option>
            </select>
        </div>
        </div>
    <div class="form-group">
        <div class="col-md-5">
            <label for="Name">MobileNumber</label>
        </div>
        <div class="col-md-5">
            <input class="text-box single-line" name="MobileNumber" type="text">
        </div>
        </div>
    <div class="form-group">
        <div class="col-md-5">
            <label for="Name">Complaint</label>
        </div>
        <div class="col-md-5">
            <textarea class="text-box single-line" name="Complaint"></textarea>
        </div>
        </div>


    <div class="col-md-5">
        <input type="submit" value="Create" class="btn btn-default">
    </div>
</form>

If you do not want to use submit then you can use ajax.

sina_Islam
  • 1,068
  • 12
  • 19