0

I'm a new learner of ASP.NET MVC. This problem should be easy to answer for professions. I'm trying to submit a form (post comment), and getting error.

Here is my controller

[HttpPost]
public ActionResult Index(long id, CommentViewModel comment) {
    var service = new UserService();
    var articleService = new ArticleService();
    comment.UserId = service.GetUserByUsername(User.Identity.Name).UserId;
    comment.ArticleId = id;
    comment.CommentTime = DateTime.Now;
    articleService.AddArticleComment(comment);
    return View();
}

here is my ViewModel

public class CommentViewModel : BaseViewModel {
    public Int64 CommentId { get; set; }
    public Int64 UserId { get; set; }
    public Int64 ArticleId { get; set; }
    public DateTime CommentTime { get; set; }
    public String CommentBody { get; set; }
}

here is my View (HTML)

<form class="form-stacked" id="comment-form" action="@Url.Action("Index", "Article")"   method="post" enctype="multipart/form-data">
    <label class="control-label" for="commentTextArea">Leave a comment...</label>
    <textarea rows="3" id="commentTextArea" name="commentBody" class="span8"></textarea>
                <input type="submit" value="Post Comment" />
</form>

this is URL

http://localhost:58856/Article?Id=1

and this is the Error Message

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method 'System.Web.Mvc.ActionResult Index(Int64, TechCells.Services.ViewModels.CommentViewModel)' in 'TechCells.Web.UI.Controllers.ArticleController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

I guess MVC should automatically detect the id from the URL, and automatically assign ViewModel properties based on names. Right?

What is the reason for this error? How can I fix?

Thanks.

2
  • What does your route registration code look like? Commented Jun 22, 2013 at 21:06
  • @Jasen, It has only default route registration. routes.MapRoute( name: "TcMainRoute", url: "{controller}/{action}", defaults: new { controller = "Home", action = "Index", }); Commented Jun 23, 2013 at 6:48

2 Answers 2

2

Your form doesn't have an <input name="id" /> (which is necessary per your action signature). Remember that MVC's action arguments are incoming values, so if this is a form submit, all those parameters need to be supplied (though sometimes they can be defaulted in a route definition, but I won't get in to that).

Mis-read and missed the Id coming from a GET parameter. Assuming you follow traditional form handling with a GET & POST action, you're passing the Id to the GET, it renders a view, then on POST the Id's dropped. So, two options:

  • If you don't need it, remove the long id parameter or make it optional (line id = 0) so that MVC can carry on with a default value.
  • If you do need it, make sure to pass it off in your Url.Action() as a routeValue so it's received back in.

Also, don't be afraid to use the HTML Helpers, like Html.BeginForm, Html.LabelFor, Html.TextBoxFor, etc.

@using (Html.BeginForm("Index", "Article",
  new { id = __ID_FROM_GET_REQUEST_ }, // to hand-off to POST action
  FormMethod.Post,
  new { enctype = "multipart/form-data" }
))
{
    @* I assume these are here to help reference what the comment is regarding *@
    @Html.HiddenFor(x => x.UserId)
    @Html.HiddenFor(x => x.ArticleId)

    @* are these ones auto-generated at creation time? if so, remove these. I
       don't know enough about your work-flow, so just going to place them for
       now. I also don't know what your validation requirements are. *@
    @Html.HiddenFor(x => x.CommentId)
    @Html.HiddenFor(x => x.CommentTime)

    @* Now we get in to user-interaction *@
    @Html.LabelFor(x => x.CommentBody)
    @Html.TextAreaFor(x => x.CommentBody, new { @class = "span8", rows = "3" })

    <input type="submit" value="Post Comment" />
}

Then for LabelFor to work, make sure you decorate your model:

/* ...snip ... **/

[Display(Name = "Leave a comment...")]
public String CommentBody { get; set; }

/* ...snip ... **/
Sign up to request clarification or add additional context in comments.

7 Comments

You mean: long id = 0? And what about nullable?
@OzrenTkalčecKrznarić: Either, though I suppose long? would be a better fit (given it flags an absent value more concisely).
i need id, to get the current article id from query string. but MVC automatically recognizes the id in the query string, right? look at the URL, there is id=1. why it is not getting the id automatically?
@TechCells.net: your'e not invoking Index action, try with localhost:58856/Article/Index?Id=1
@TechCells.net: Touche, missed that it's a GET parameter and not a POST. In that case it's probbaly because the URL you're generating to submit to is dropping the id (your Url.Action()).
|
0

Changing it to this

public ActionResult Index(long id = 0, CommentViewModel comment)

OR

this

public ActionResult Index(long? id, CommentViewModel comment)

will solve the problem.

The error is occuring because you are not passing any value for id. and id is not nullable. To solve this, either pass id or change the method signature as above.

2 Comments

id cannot be null, and cannot be 0. it should have some valid value.
In that case, You can either determine id in the code OR send id from the view using any input control like dropdown or hidden field.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.