locked
Model Id always gets 0 on httpost while update the model RRS feed

  • Question

  • User1052662409 posted

    Hi All,

    Below is my view

    @using (Html.BeginForm("Edit", "Enquiry", FormMethod.Post))
    {
        @Html.AntiForgeryToken()
        <div class="wrapper-content" style="margin-left: 272px;">
            <div class="row">
                <div class="col-lg-12">
    
                    <div class="widgets-container">
    
                        <div class="form-horizontal m-t-xs">
                            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                            @Html.HiddenFor(model => model.EnquiryId)
                            <div class="form-group">
                                @Html.LabelFor(model => model.ProjectNumber, htmlAttributes: new { @class = "control-label col-md-2" })
                                <div class="col-md-8">
                                    @Html.TextBoxFor(model => model.ProjectNumber, null, new { @class = "form-control", @id = "txtProject" })
                                    @Html.ValidationMessageFor(model => model.ProjectNumber, "", new { @class = "text-danger" })
                                </div>
                            </div>
    <div class="form-group">
    @Html.LabelFor(model => model.Image, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-8">
    @Html.TextBoxFor(model => model.Image, new { type = "file", @class = "form-control" })
    @Html.ValidationMessageFor(model => model.Image, "", new { @class = "text-danger" })
    </div>
    </div> ..... so on

    And this is my model

     public class EnquiryModel
        {
            public long EnquiryId { get; set; }
            
            public string Demand { get; set; }
            
            public string Description { get; set; }
            
            public string Remark { get; set; }
           
            public string ProjectNumber { get; set; }
            
            public string Image { get; set; }
           
            public string RequestStatus { get; set; }
        }

    and the below part is my Action Result



    public ActionResult Edit(int id)
    {
    DataAccessLayer objDB = new DataAccessLayer();
    return View(objDB.Enquiry_SelectById(id));
    }


    [HttpPost] public ActionResult Edit(EnquiryModel EM, HttpPostedFileBase Image) { try { DataAccessLayer objDB = new DataAccessLayer(); if (Image != null && Image.ContentLength > 0) { EM.Image = UploadFile(Image).ToString(); } else { EM.Image = ""; } objDB.Enquiry_Update(EM); return RedirectToAction("Index"); } catch (Exception ex) { return View(); } }

    And the Edit Action result called the page's url is ok like http://localhost:65099/Enquiry/Edit/8

    But why the EnquiryId always gets 0? And even HttpPostedFileBase Image always shows null even after selection a file?

    I guess the both issue indication a single mistake.

    Please suggest.

    Thursday, June 27, 2019 11:09 AM

Answers

  • User1520731567 posted

    Hi demoninside9,

     public ActionResult Edit(int id)
            {
                DataAccessLayer objDB = new DataAccessLayer();
                return View(objDB.Enquiry_SelectById(id));
            }

    I guess the problem is on the GET method.

    How is your DataAccessLayer?

    You should make sure that GET action return a record whose model type is EnquiryModel,and EnquiryId has value.

    Generally,get action code like:

     public ActionResult Edit(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
    EnquiryModel model= db.xxx.Find(id);//for example:return EnquiryId=1,Demand="aaa",Description="bbb"...
    if (model== null) { return HttpNotFound(); } return View(model); }

    @Html.HiddenFor(model => model.EnquiryId)

    Then,Hidden Field can receive value from model,and HTTPPOST action also can get value from html tag whose name is EnquiryId.

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 28, 2019 7:35 AM
  • User753101303 posted

    So the next logical step is to check how the EnquiryId property of your model is populated. My guess is that is left to its default value rather than being assigned from the "Id" property of the entity you loaded (and that itself should match the source value found as a parameter in the url).

    In short it confirms the problem is in Enquirty_SelectById as someone suggested already. When you see a value is wrong, just always check the place where it is supposed to be populated (and if the source value is wrong at this step, go check the previous place) until you find where the value is not transmitted correctly from one step to the next.

    Edit: sorry I missed the code you posted earlier. You create a new EnquiryModel but you never assign obj.EnquiryId.

    If you want to keep using ADO.NET you could use https://docs.microsoft.com/en-us/dotnet/api/system.data.datarowextensions?view=netframework-4.8 which allows to write this using :
    obj.EnquiryId=dt.Rows[0].Fields<int>("EnquiryID"); 

    You could also to consider using EF either fully or using something such as https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.database.sqlquery?view=entity-framework-6.2.0#System_Data_Entity_Database_SqlQuery__1_System_String_System_Object___ that will automatically assign each property from the corresponding column name.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 28, 2019 12:45 PM

All replies

  • User475983607 posted

    There can be a bug in...

    objDB.Enquiry_SelectById(id)

    Or..

    objDB.Enquiry_Update(EM);

    I recommend standard troubleshooting steps.  Use the Browser Dev Tools (F12) to verify the ID in submitted to the server.  Use the Visual Studio debugger to verify the logic (we cannot see) is functioning as expected.

    Thursday, June 27, 2019 11:41 AM
  • User753101303 posted

    Hi,

    I would use "view source" in  the browser to look at the actualHTML markup and see which value is found in the hidden field (and then F12 as suggested already). In short the idea is just to check the value all along from where it is supposed to come from.

    For file upload you need to use multipart/form-data as show for example at https://stackoverflow.com/questions/216600/html-beginform-and-adding-properties (and so for now it is perhaps not the same issue).

    Thursday, June 27, 2019 11:56 AM
  • User1520731567 posted

    Hi demoninside9,

     public ActionResult Edit(int id)
            {
                DataAccessLayer objDB = new DataAccessLayer();
                return View(objDB.Enquiry_SelectById(id));
            }

    I guess the problem is on the GET method.

    How is your DataAccessLayer?

    You should make sure that GET action return a record whose model type is EnquiryModel,and EnquiryId has value.

    Generally,get action code like:

     public ActionResult Edit(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
    EnquiryModel model= db.xxx.Find(id);//for example:return EnquiryId=1,Demand="aaa",Description="bbb"...
    if (model== null) { return HttpNotFound(); } return View(model); }

    @Html.HiddenFor(model => model.EnquiryId)

    Then,Hidden Field can receive value from model,and HTTPPOST action also can get value from html tag whose name is EnquiryId.

    Best Regards.

    Yuki Tao

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 28, 2019 7:35 AM
  • User1052662409 posted

    I would use "view source" in  the browser to look at the actualHTML markup and see which value is found in the hidden field (and then F12 as suggested already). In short the idea is just to check the value all along from where it is supposed to come from.

    it shows hidden field as below

    <input data-val="true" data-val-number="The field EnquiryId must be a number." data-val-required="The EnquiryId field is required." id="EnquiryId" name="EnquiryId" type="hidden" value="0" />
    

    But not getting why it is showing value as 0 instead of 8 as I can see my url is like http://localhost:65099/Enquiry/Edit/8

    Friday, June 28, 2019 12:38 PM
  • User1052662409 posted

    How is your DataAccessLayer?

     public EnquiryModel Enquiry_SelectById(int id)
            {
                EnquiryModel obj = null;
                Hashtable param = new Hashtable();
                param.Add("@enquiry_id", id);
                param.Add("@case", 2);
                DataTable dt = new DataTable();
                dt = oDBHelper.GetDatatable("usp_enquiry_details", param);
                obj = new EnquiryModel();
                obj.ProjectNumber = dt.Rows[0]["ProjectNumber"].ToString();
                obj.Demand = dt.Rows[0]["Demand"].ToString();
                obj.Description = dt.Rows[0]["Description"].ToString();
                obj.Image = dt.Rows[0]["Image"].ToString();
                return obj;
            }

    Below is my sp

    SELECT enquiry_id AS EnquiryId, demand AS Demand, description AS Description, remark AS Remark ,  projectno AS ProjectNumber, vcimage AS Image
    		   FROM tblEnquiry 
    		   WHERE enquiry_id=@enquiry_id

    The model as follows

    public class EnquiryModel
        {
            public long EnquiryId { get; set; }
           
            public string Demand { get; set; }
           
            public string Description { get; set; }
          
            public string Remark { get; set; }
          
            public string ProjectNumber { get; set; }
           
            public string Image { get; set; }
           
            public string RequestStatus { get; set; }
        }

    and below is get method

     // GET: Enquiry/Edit/5
            public ActionResult Edit(int id)
            {
                DataAccessLayer objDB = new DataAccessLayer();
                return View(objDB.Enquiry_SelectById(id));
            }

    Friday, June 28, 2019 12:43 PM
  • User753101303 posted

    So the next logical step is to check how the EnquiryId property of your model is populated. My guess is that is left to its default value rather than being assigned from the "Id" property of the entity you loaded (and that itself should match the source value found as a parameter in the url).

    In short it confirms the problem is in Enquirty_SelectById as someone suggested already. When you see a value is wrong, just always check the place where it is supposed to be populated (and if the source value is wrong at this step, go check the previous place) until you find where the value is not transmitted correctly from one step to the next.

    Edit: sorry I missed the code you posted earlier. You create a new EnquiryModel but you never assign obj.EnquiryId.

    If you want to keep using ADO.NET you could use https://docs.microsoft.com/en-us/dotnet/api/system.data.datarowextensions?view=netframework-4.8 which allows to write this using :
    obj.EnquiryId=dt.Rows[0].Fields<int>("EnquiryID"); 

    You could also to consider using EF either fully or using something such as https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.database.sqlquery?view=entity-framework-6.2.0#System_Data_Entity_Database_SqlQuery__1_System_String_System_Object___ that will automatically assign each property from the corresponding column name.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 28, 2019 12:45 PM
  • User1052662409 posted

    obj.EnquiryId=dt.Rows[0].Fields<int>("EnquiryID"); 

    Phew... What a silly mistake I did ans even did not notice it. Thank you  ParriceSc Sir

    :) Thanks a lot

    Friday, June 28, 2019 1:11 PM