30

I'm stumped with this one and your help would be most appreicated.

I get the error:

The parameter conversion from type 'System.String' to type 'DataPortal.Models.EntityClasses.FeedbackComment' failed because no type converter can convert between these types

The ModelState.IsValid is failing on the FeedbackComment.Comment property

Any ideas?

public class FeedbackComment : IFeedbackComment
{
    [Key]
    public int Id { get; set;}

    public int FeedbackId { get; set; }

     [Required(ErrorMessage = "Please enter a Comment")]
    public string Comment { get; set; }

    public DateTime CommentDate { get; set; }

    public string CommentBy { get; set; }
}

Controller Methods

//
    // GET: /FeedbackComment/Create

    public virtual ActionResult Create(int feedbackId)
    {
        var comment = new FeedbackComment {FeedbackId = feedbackId, CommentBy = User.Identity.Name, CommentDate = DateTime.Now};
        return View(comment);
    } 

    //
    // POST: /FeedbackComment/Create

    [HttpPost]
    public virtual ActionResult Create(FeedbackComment comment)
    {

        if (ModelState.IsValid)
        {

            _feedbackCommentRepository.Add(comment);

            return RedirectToAction(MVC.Feedback.Details(comment.FeedbackId));
        }

        return View(comment);
    }

And the view

@model DataPortal.Models.EntityClasses.FeedbackComment
@{
ViewBag.Title = "Create Comment";
}
<h2>Create Comment</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
    <legend>Feedback Comment</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Comment)
    </div>
    <div class="editor-field">
        @Html.TextAreaFor(model => model.Comment, new{@class = "TextEditor"})
        @Html.ValidationMessageFor(model => model.Comment)
    </div>


    @Html.HiddenFor(model=> model.CommentDate)
    @Html.HiddenFor(model=> model.CommentBy)       
    @Html.HiddenFor(model=> model.FeedbackId)

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

<div>
@Html.ActionLink("Back to Comment Details", MVC.Feedback.Details(Model.FeedbackId))
</div>
Stacked
  • 6,892
  • 7
  • 57
  • 73
MrBliz
  • 5,830
  • 15
  • 57
  • 81
  • 2
    Try changing the FeedbackComment parameter name in your POST action. Also you should set CommentBy and CommentDate in your POST action rather than using a hidden field – epzee Nov 02 '11 at 16:22
  • Thank you very much for your secondary tip. – MrBliz Nov 02 '11 at 16:35

4 Answers4

82

The problem is the name of your action parameter:

public virtual ActionResult Create(FeedbackComment comment)

It's called comment. But your FeedbackComment also has a property called Comment of type string. So the default model binder gets crazy. Just rename one of the two to avoid the conflict.

For example the following will fix your issue:

public virtual ActionResult Create(FeedbackComment model)
{
    if (ModelState.IsValid)
    {
        _feedbackCommentRepository.Add(model);
        return RedirectToAction(MVC.Feedback.Details(model.FeedbackId));
    }
    return View(model);
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    Ah, of course, makes complete sense when you think about it. Always thought you'd be safe from those kind of shenanigans as c# is case sensitive. Thank you very much. – MrBliz Nov 02 '11 at 16:34
  • 1
    Incredible amounts of time wasted with this error. +1 for you and thanks! – Matty May 26 '15 at 23:08
  • 1
    This is so difficult to debug it should be a compiler warning or something. The chances that the model variable is going to relate to the content and have the same name as of it's parameters is extremely high. – m12lrpv Sep 17 '15 at 10:41
  • 1
    WOW! I was working on a problem similar to this for the last 3 hours. Thank you so much! – Chris Lees Dec 07 '15 at 21:54
  • "gets crazy" indeed! – Yehuda Kremer Nov 14 '19 at 13:13
  • I had an issue like this as well, thanks. – jamie Sep 28 '21 at 15:30
1

I had the same name for the parameter on the GET method

[HttpGet]
public ActionResult Create(int OSSB)

.. and a property from Faturamento model, that was used on the POST method

[HttpPost]
public ActionResult Create(Faturamento model)

Just like this..

public class Faturamento {
        [Column("ID_OSSB")]
        public virtual int ID_OSSB { get; set; }
        [ForeignKey("ID_OSSB")]
        public virtual OSSB OSSB { get; set; }
        ...
}

What solved for me was changing the GET parameter name:

[HttpGet]
public ActionResult Create(int IDOSSB)
Rafael Araújo
  • 3,524
  • 1
  • 14
  • 14
0

I had the same error but the cause was different from the accepted answer. Adding a custom ModelBinder fixed it for me.

I created a CData class as described here

How do you serialize a string as CDATA using XmlSerializer? (it's the last answer unless it got voted up because it's a great solution)

I serialize my ViewModel to XML. When I set a type in a property in my ViewModel to CData, it will automatically be serialized to a CData section and deserialized to a CData field. (which is great!)

When I do a post action in my view I want to keep some fields in my ViewModel so they are added as Html.HiddenFor in the form.

When a submit is done, an error occurs (the one in the title). The model binder tries to bind a string field to a CData field which fails.

A custom model binder for the CData type fixes this

public class CDataModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        return new CData(result.AttemptedValue);
    }
}

Global.asax

 ModelBinders.Binders.Add(typeof(CData), new CDataModelBinder());
Community
  • 1
  • 1
MonkeyDreamzzz
  • 3,978
  • 1
  • 39
  • 36
0

In my case I was writing a model class name in Html Helper class. which was getting it failed as it was expecting a System.String datatype and I was passing a custom class name.

Jamshaid K.
  • 3,555
  • 1
  • 27
  • 42