0

I want create form, but fill it via js later, not by asp.net on server-render time.

Is it possible to create form without a model object, only by class metadata?
For example: when I'm creating editor for field, I use code like @Html.EditorFor(contact => contact.FirstName) which will try to access the FirstName property and, if there no model @Html.Partial("EditModal", (Contact)null), it will throw exception saying

"The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[Contact]', but this dictionary requires a model item of type 'Contact'."

Shishkin Pavel
  • 351
  • 2
  • 19
  • Just use plain html. If you are not sure how to do that, just browse a page containing a form and right click and view page source. You will be able to see the rendered html – It's a trap Mar 28 '17 at 09:22
  • Just pass a default instance of your model to the view. –  Mar 28 '17 at 09:26
  • @It'satrap so, there no other way? Using these helpers ensures at least you have correct names on both server and client-side and may be some other features. – Shishkin Pavel Mar 28 '17 at 09:26
  • And it will no 'crash' if you have a `@model YourModel` declaration in the view so its not clear what your saying –  Mar 28 '17 at 09:27
  • @StephenMuecke I already used this, but it seems like a hack – Shishkin Pavel Mar 28 '17 at 09:28
  • 1
    What? Why do you think its a hack. And you do not even need to pass a model - its just good practice. And the `HtmlHelper` methods use the models `ModelMetadata` so a model is not necessary, just the declaration in the view (and it does not 'crash') –  Mar 28 '17 at 09:30
  • 1
    While writing HTML, you have to be careful that "name" property matches the field name of your model. There is nothing else you need to do this way. I am using the same approach in my website. Also using C# to render these basic HTML would be a performance disadvantage. Still anyway you can follow what Stephen is saying. That should work. – It's a trap Mar 28 '17 at 09:31
  • @StephenMuecke if there is "Index" page with `List` set up as model and I want create, for example, modal window with edit dialog, if I pass `(Contact) null` to partial view with `Contact` model, exception thrown "The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[Contact]', but this dictionary requires a model item of type 'Contact'." Btw, if I'll pass just `new Contact`, it will work – Shishkin Pavel Mar 28 '17 at 09:38
  • That has nothing to do with using the `HtmlHelper` methods. And refer [this answer](http://stackoverflow.com/questions/40373595/the-model-item-passed-into-the-dictionary-is-of-type-but-this-dictionary-requ) for an explanation of that error (the section titled _Passing the wrong model from a view to a partial view_). But don't use `Partial()` - use `@Html.Action()` instead –  Mar 28 '17 at 09:43
  • 1
    And not using the `HtmlHelper` methods mean you lose all the benefits of model binding, client side validation etc. (writing the html manually is just crazy) –  Mar 28 '17 at 09:45
  • @StephenMuecke can't understand how `@Html.Action` will help there. there is 'Index' page with some editing modal hidden dialog rendered by aspnet, not an action link. Also modal rendered as `@Html.Partial("EditModal", (Contact)null)` but still throws exception "The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[Contact]', but this dictionary requires a model item of type 'Contact'." ('Index' page has `@model IEnumerable`) – Shishkin Pavel Mar 28 '17 at 09:52
  • 1
    Create a `[ChildActionOnly]` method that returns a partial view of your form/dialog that adds the new `Contact` (and that partial will have `@model Contact`) Then in the main view use `@Html.Action("yourActionName")` to render the view. In that method you could just have `return View();`, although I do not understand why you do not want to follow good practice and use `return View(new Contact());` –  Mar 28 '17 at 09:56
  • 1
    And `@Html.Action()` is not `@Html.ActionLink()` :) –  Mar 28 '17 at 09:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139232/discussion-between-stephen-muecke-and-shishkin-pavel). –  Mar 28 '17 at 10:06

3 Answers3

2

The error your getting has nothing to do with using the HtmlHelper methods. It occurs because your EditModal partial has a @model Contact declaration and you calling it using @Html.Partial() without passing it an instance of Contact, so by default it passes the model in the main view witch is List<Contact> - they are not the same, hence the error. For more explanation, refer The model item passed into the dictionary is of type .. but this dictionary requires a model item of type.

The HtmlHelper methods do not need a model because they use ModelMetadata to generate the html attributes of the form control (and will use the models default values to generate the value attribute if the model is null).

You can fix the error by simply using @Html.Partial("EditModal", new Contact()) to pass a default instance of your model. From the comments, its not clear why you specifically do not want to do that (its good practice and has no measurable performance impact). But as an alternative you can use @Html.Action() to generate the dialog/form. Create a method in your controller, say

[ChildActionOnly]
public PartialViewResult EditModal()
{
    return View(); // not passing a model
}

and in the main view, use (assuming the method is in the same Controller)

@Html.Action("EditModal") // or @{ Html.RenderAction("EditModal"); }

to render the partial without passing it a model.

But its still good practice to use return view(new Contact()); so that you do pass a new instance of the model to the view (and it will save you pain later when trying to track down errors such as when someone adds say <div>@Model.SomeProperty</div> in the partial which will throw a NullReferenceException).

Community
  • 1
  • 1
1

Just use plain html <input type="text" name="FirstName" id="FirstName" />

<script> myFunction(); function myFunction() { document.getElementById("FirstName").value = "Johnny Bravo"; <input type="text" name="FirstName" id="FirstName" /> </script>

Arun kumar
  • 1,535
  • 3
  • 12
  • 17
0

You can use a binding framework, an example is knockoutjs, so you will use Editor instead of EditorFor

Hassan Alhaj
  • 333
  • 3
  • 11