Ken-F
Ken-F

Reputation: 152

MVC CRUD: going from create directly to udpate

I have a relatively simple flow:

posting an item -> preview of post -> option A: edit | option B: publish

Everything is working as expected, using standard CRUD whenever possible. However, in the scenario where an item is being posted, then going to preview screen and the user would like to publish (which essentially is just changing a bool from false to true in the DB) I get the following error message:

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

As in standard CRUD, I call the ID of the item when editing, but when moving from create to preview, there seems to be no logic way to call the ID as it is just being created. However, with the extra step in between, I think the issue lies with me trying to edit without having a ID specified in the preview view.

Here my controller code for the publishing part:

    //POST: /errandom/errandPreview
    public ActionResult ConfirmErrand()
    {
        // define variables for reuse
        var userID = User.Identity.GetUserId();
        DateTime nowUTC = DateTime.Now.ToUniversalTime();
        DateTime nowLocal = DateTime.Now.ToLocalTime();
        // define errand
        var errand = new errands
        {
            // form
            Published = true
        };
        // save errand to DB
        ERRANDOM.Entry(errand).State = EntityState.Modified;
        ERRANDOM.SaveChanges();
        return RedirectToAction("Index");
    }

Plus the view for completeness:

<section id="errandPreview" class="manageForm">
    @using (Html.BeginForm("errandPreviewForm", "errandom", FormMethod.Post, new { @id = "errandPreviewForm", @class = "form-horizontal", @role = "form" }))
    {
        @Html.AntiForgeryToken()
        @Html.HiddenFor(m => m.LatitudePosted, new { @id = "errandPreviewLatitudePosted", @class = "userActivity" })
        @Html.HiddenFor(m => m.LongitudePosted, new { @id = "errandPreviewLongitudePosted", @class = "userActivity" })
        @Html.HiddenFor(m => m.LocationPosted, new { @id = "errandPreviewUserLocationPosted", @class = "userActivity" })
        @Html.HiddenFor(m => m.ID, new { @id = "errandPreviewID", @class = "errandPreviewID" })
    <div id="errandPreviewErrandSection" class="manageSection">
        <p id="errandPreviewErrandSectionTitle" class="manageSectionTitle">
            @Html.DisplayFor(m => m.Title)
        </p>
        <div id="errandPreviewCategoryArea" class="manageArea row">
            <div id="errandPreviewDateTimePostedDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10">
                @Html.DisplayNameFor(m => m.DateTimePosted)
            </div>
            <div id="errandPreviewDateTimePostedDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10">
                @Html.DisplayFor(m => m.DateTimePosted)
            </div>
            <div id="errandPreviewCategoryDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-5 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.Category)
            </div>
            <div id="errandPreviewSubCategoryDisplayName" class="errandomDisplayName col-xs-5 col-sm-5 col-md-5 col-lg-5">
                @Html.DisplayNameFor(m => m.SubCategory)
            </div>
            <div id="errandPreviewCategoryDisplay" class="errandomDisplay col-xs-offset-1 col-xs-5 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayFor(m => m.Category)
            </div>
            <div id="errandPreviewSubCategoryDisplay" class="errandomDisplay col-xs-5 col-sm-5 col-md-5 col-lg-5">
                @Html.DisplayFor(m => m.SubCategory)
            </div>
        </div>
        <hr />
        <div id="errandPreviewDescriptionArea" class="manageArea row">
            <div id="errandPreviewPictureDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-3 col-md-offset-1 col-md-3 col-lg-offset-1 col-lg-3">
                <img id="errandPreviewPicture" class="errandPreviewPicture" src="@Url.Action("errandPicture", "errandom")" />
            </div>
            <div id="errandPreviewDescriptionDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-0 col-sm-7 col-md-offset-0 col-md-7 col-lg-offset-0 col-lg-7">
                @Html.DisplayFor(m => m.Description)
            </div>
        </div>
        <hr />
        <div id="errandPreviewLocationArea" class="manageArea row">
            <div id="errandPreviewLocationDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10">
                @Html.DisplayNameFor(m => m.Location)
            </div>
            <div id="errandPreviewLocationDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10">
                @Html.DisplayFor(m => m.Location)
                @Html.HiddenFor(m => m.Location, new { @id = "errandPreviewLocationDisplayValue", @class = "manageDisplay" })
            </div>
            <div id="errandPreviewMapDisplayFrame" class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <div id="errandPreviewMapDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10">
                </div>
            </div>
        </div>
        <hr />
        <div id="errandPreviewTimeArea" class="manageArea row">
            <div id="errandPreviewASAPDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-5 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.ASAP)
            </div>
            <div id="errandPreviewASAPDisplay" class="errandomDisplay col-xs-offset-0 col-xs-5 col-sm-offset-0 col-sm-5 col-md-offset-0 col-md-5 col-lg-offset-0 col-lg-5">
                @Html.DisplayFor(m => m.ASAP)
            </div>
            <div id="errandPreviewStartDateTimeDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.StartDateTime)
            </div>
            <div id="errandPreviewStartDateTimeDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-0 col-sm-5 col-md-offset-0 col-md-5 col-lg-offset-0 col-lg-5">
                @Html.DisplayFor(m => m.StartDateTime)
            </div>
            <div id="errandPreviewEndDateTimeDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.EndDateTime)
            </div>
            <div id="errandPreviewEndDateTimeDisplay" class="errandomDisplay col-xs-offset-1 col-xs-10 col-sm-offset-0 col-sm-5 col-md-offset-0 col-md-5 col-lg-offset-0 col-lg-5">
                @Html.DisplayFor(m => m.EndDateTime)
            </div>
            <div id="errandPreviewDurationInHoursDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-5 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.DurationInHours)
            </div>
            <div id="errandPreviewDurationInHoursDisplay" class="errandomDisplay col-xs-offset-0 col-xs-5 col-sm-offset-0 col-sm-5 col-md-offset-0 col-md-5 col-lg-offset-0 col-lg-5">
                @Html.DisplayFor(m => m.DurationInHours)
            </div>
        </div>
        <hr />
        <div id="errandPreviewOfferingArea" class="manageArea row">
            <div id="errandPreviewOfferingDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-5 col-sm-offset-1 col-sm-5 col-md-offset-1 col-md-5 col-lg-offset-1 col-lg-5">
                @Html.DisplayNameFor(m => m.Offering)
            </div>
            <div id="errandPreviewPaymentMethodDisplayName" class="errandomDisplayName col-xs-5 col-sm-5 col-md-5 col-lg-5">
                @Html.DisplayNameFor(m => m.PaymentMethod)
            </div>
            <div id="errandPreviewCurrencyDisplay" class="errandomDisplay col-xs-offset-1 col-xs-2 col-sm-offset-1 col-sm-1 col-md-offset-1 col-md-1 col-lg-offset-1 col-lg-1">
                @Html.DisplayFor(m => m.Currency)
            </div>
            <div id="errandPreviewOfferingDisplay" class="errandomDisplay col-xs-offset-0 col-xs-3 col-sm-offset-0 col-sm-4 col-md-offset-0 col-md-4 col-lg-offset-0 col-lg-4">
                @Html.DisplayFor(m => m.Offering)
            </div>
            <div id="errandPreviewPaymentMethodDisplay" class="errandomDisplay col-xs-5 col-sm-5 col-md-5 col-lg-5">
                @Html.DisplayFor(m => m.PaymentMethod)
            </div>
            <div id="errandPreviewPriceDisplayName" class="errandomDisplayName col-xs-offset-1 col-xs-12 col-sm-offset-1 col-sm-12 col-md-offset-1 col-md-12 col-lg-offset-1 col-lg-12">
                @Html.DisplayNameFor(m => m.Price)
            </div>
            <div id="errandPreviewPriceDisplay" class="errandomDisplay col-xs-offset-1 col-xs-12 col-sm-offset-1 col-sm-12 col-md-offset-1 col-md-12 col-lg-offset-1 col-lg-12">
                @Html.DisplayFor(m => m.Price)
            </div>
        </div>
        <hr />
        <div id="errandPreviewUserArea" class="manageArea row">
            <div id="errandPreviewUserPictureDisplay" class="errandomDisplay col-xs-offset-1 col-xs-3 col-sm-offset-1 col-sm-2 col-md-offset-1 col-md-2 col-lg-offset-1 col-lg-2">
                <img id="errandPreviewUserPicture" class="errandPreviewUserPicture" src="@Url.Action("UserPicture", "Manage")" />
            </div>
            <div id="errandPreviewFirstNameDisplay" class="errandomDisplay col-xs-7 col-sm-8 col-md-8 col-lg-8">
                @Html.DisplayFor(m => m.FirstName)
                @*link to contact for questions*@
                @Html.DisplayFor(m => m.Rating)
            </div>
        </div>
    </div>
        <div id="errandPreviewButtonSection" class="manageSection">
            <div id="errandPreviewButtonArea" class="manageArea row">
                @Html.ActionLink("Edit", "EditErrand", "errandom", new { ID = Model.ID }, htmlAttributes: new { @id = "errandPreviewEditButton", @class = "manageButton col-xs-5 col-sm-5 col-md-5 col-lg-5" })
                <div id="errandPreviewButtonSeparator" class="manageSeparator col-xs-2 col-sm-2 col-md-2 col-lg-2"></div>
                @Html.ActionLink("Post", "ConfirmErrand", "errandom", new { ID = Model.ID }, htmlAttributes: new { @id = "errandPreviewPostButton", @class = "manageButton col-xs-5 col-sm-5 col-md-5 col-lg-5" })
            </div>
        </div>
    }
</section>

Any idea where I am going wrong? As said, the goal should be to go from CREATE directly to PREVIEW (which essentially is a trimmed down UPDATE) and then back to INDEX.

Upvotes: 1

Views: 51

Answers (1)

Willy David Jr
Willy David Jr

Reputation: 9131

As far as I understand your problem, you want to preview before publishing, and if you already saved the record, you can get the ID using this:

//POST: /errandom/errandPreview
public ActionResult ConfirmErrand(int? ID) //Add this parameter to get record ID
{
    //Your other logic here..

    var errand = ERRANDOM.errands.Find(ID); //Find your record 
    errand.Published = true; 

    //Update errand to DB
    ERRANDOM.Entry(errand).State = EntityState.Modified;
    ERRANDOM.SaveChanges();
    return RedirectToAction("Index");
}

You can get the record using the Find method, since you are passing the ID on your code on your existing code of your View here:

@Html.ActionLink("Post", "ConfirmErrand", "errandom", new { ID = Model.ID }, htmlAttributes: new { @id = "errandPreviewPostButton", @class = "manageButton col-xs-5 col-sm-5 col-md-5 col-lg-5" })

Upvotes: 1

Related Questions