Submit na stronie ze strony ASP.NET

0

Witam.
Dopiero uczę się ASP więc proszę o wybaczenie jeżeli mój problem wyda się lamerski.
Tworzę stronę w standardzie MVC.
Wywołuję stronę na której edytuję parametry użytkownika i zapisuję je poleceniem "Submit". Z tej strony wywołuję inną stronę, na której definiuję dodatkowe podpozycje parametrów użytkownika, które zwracam poprzez polecenie "Submit" po którym wracam na poprzednią stronę z edycją parametrów użytkownika. I tu mam problem ponieważ po wywołaniu i zapisie tej dodatkowej strony wywołanie polecenia "Submit" na stronie pierwszej wywołuje mi metodę HttpPost ale tej dodatkowej, już zamkniętej prawidłowo strony. Jeżeli tej dodatkowej strony nie wywołam to wszystko jest ok.
Co robię źle?
Obydwie strony strony są napisane tak samo. Po zapisaniu każdej strony wywołuję Model.Clear() a;e to nie pomaga.
Muszą przekazać parametry wprowadzane przez użytkownika na drugiej stronie do pierwszej strony. Doczytałem że mogę to zrobić jedynie przez polecenie Submit. Ale czemu Submit wywołuje mi metodą zamkniętej już strony?
Z góry dziękuję za pomoc.

1

Co nazywasz "poleceniem Submit" i jak z jednej strony wywołujesz inną stronę? Pokaż też jakiś kod.

0

Koledze chodzi chyba o form submit. Tak jak somekind napisał, daj kod. Spróbuj też opisać problem mniej chaotycznie.

0

Ok, może rzeczywiście za dużo chaosu. A więc po kolei.
Z kontrolera AccountController wywołuję formę submit z edycją użytkownika poniższym poleceniem:


        public ActionResult EditUser(int? id)
        {
            using (UserDBContext db = new UserDBContext())
            {
                _addedUser = null;
                if (id != null)
                    _editedUser = db.GetActiveUser(id.Value);
                return View("EditUser", GetLayoutName(), _editedUser);
            }
        }

        [HttpPost]
        public ActionResult EditUser(UserAccount user)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    using (UserDBContext db = new UserDBContext())
                    {
                        db.SaveUserAccount(user);
                        ModelState.Clear();
                        return View("Index", GetLayoutName(), db.GetUsers());
                    }
                }
            }
            catch (Exception exp)
            {
                ModelState.AddModelError(string.Empty, exp.Message);
            }

            return View("EditUser", GetLayoutName(), user);
        }

Druga metoda wywoływana jest podczas zapisu formy cshtml z kontrolki input typu submit:


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
...
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Zapisz" class="btn btn-default" title="Zapisz użytkownika" />
        </div>
    </div>
</div>
}

Na tej formie mam listę dodatkową parametrów użytkownika:

<table class="table">
        <tr>
            <th>
                <p>Nazwa lokalu</p>
            </th>
            <th>
                <p>Adres IP</p>
            </th>
            <th>
                <p>Port SQL</p>
            </th>
            <th>
                <p>Użytkownik</p>
            </th>
            <th>
                <p>Hasło</p>
            </th>
            <th>
                <p>Nazwa bazy</p>
            </th>
        </tr>

        @foreach (var item in Model.Connections)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.LocalName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SqlIP)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SqlPort)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SqlUser)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SqlPassword)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.DBName)
                </td>
            </tr>
        }

    </table>

    <div>
        @Html.ActionLink("Dodaj", "AddConnection", new { })
    </div>

ActionLink "Dodaj" wywołuje metodę z tego samego kontrolera która otwiera widok do wprowadzania dodatkowych parametrów użytkownika dla powyższej listy:


        public ActionResult AddConnection()
        {
            return View("AddConnection", GetLayoutName(), new LocalConnection());
        }

        [HttpPost]
        public ActionResult AddConnection(LocalConnection connection)
        {
            if (_addedUser != null)
            {
                _addedUser.Connections.Add(connection);
                ModelState.Clear();
                return View("EditUser", GetLayoutName(), _addedUser);
            }
            if (_editedUser != null)
            {
                _editedUser.Connections.Add(connection);
                ModelState.Clear();
                return View("EditUser", GetLayoutName(), _editedUser);
            }

            return null;
        }

i forma widoku:

@model SimpleFamily.Models.LocalConnection

@{
    ViewBag.Title = "Dodanie połączenia do lokalu";
}

<h2>@ViewBag.Title</h2>

<div>
    @*@Html.ActionLink("Powrót...", "LoggedIn")*@
    <p class="btn btn-default">@Html.ActionLink("Powrót...", "EditUser", Model)</p>
    <p />
</div>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Dodanie nowego połączenia do lokalu</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @if (ViewBag.Message != null)
        {
            <div class="form-group">
                <div class="col-md-10">@ViewBag.Message</div>
            </div>
        }
        <div class="form-group">
            @Html.Label("Nazwa lokalu", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LocalName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.LocalName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.Label("Adres IP", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.SqlIP, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.SqlIP, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.Label("Port", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.SqlPort, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.SqlPort, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.Label("Nazwa bazy", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.DBName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.DBName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.Label("Użytkownik", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.SqlUser, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.SqlUser, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.Label("Hasło użytkownika", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.SqlPassword, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.SqlPassword, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Zapisz" class="btn btn-default" title="Zapisz połączenie" />
            </div>
        </div>

        <div class="form-group">
            @Html.HiddenFor(model => model.LocalID)
        </div>
    </div>
}

<div>
    @Html.ActionLink("Wróć do listy zarejestrowanych użytkowników", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

I tu zaczyna się mój problem.
Kontrolka input typu submit wywołuje metodę kontrolera "public ActionResult AddConnection(LocalConnection connection)", która to metoda otwiera ponownie widok "EditUser" z dodaną pozycją do listy.
Jednakże po tej operacji kliknięcie w kontrolkę input typu submit na widoku "EditUser" wywołuje mi metodę kontrolera "public ActionResult AddConnection(LocalConnection connection)" dla zamkniętego widoku a nie jak powinna metodę "public ActionResult EditUser(UserAccount user)".
Jeżeli nie wywołam dodatkowego widoku "AddConnection" to submit na widoku "Edituser" wywołuje prawidłową metodę kontrolera, czyli "public ActionResult EditUser(UserAccount user)".
Co robię źle?

1

Tak przede wszystkim, to:

  1. W EditUser nie powinieneś mieć return View("Index", GetLayoutName(), db.GetUsers()); tylko użyć RedirectToAction.
  2. Podobnie w AddConnection - tam powinien być RedirectToAction, a nie View.
  3. Co to są _addedUser i _editedUser? Pola statyczne?
0
somekind napisał(a):

Tak przede wszystkim, to:

  1. W EditUser nie powinieneś mieć return View("Index", GetLayoutName(), db.GetUsers()); tylko użyć RedirectToAction.
  2. Podobnie w AddConnection - tam powinien być RedirectToAction, a nie View.
  3. Co to są _addedUser i _editedUser? Pola statyczne?

Czemu mam zastosować RedirectToAction? Przecież chcę wygenerować nowy widok do wprowadzenia danych użytkownika. Tą metodą muszę wywołać nową, która i tak wywoła w końcu View?
_addesUser i _editedUser są to publiczne pola statyczne w których przechowuję opis aktualnie edytowanego lub dodawanego użytkownika (przepisuję dane z modelu widoku).

0
WojtexProgramista napisał(a):

Czemu mam zastosować RedirectToAction? Przecież chcę wygenerować nowy widok do wprowadzenia danych użytkownika.

No właśnie. A do generowania nowego widoku trzeba wejśc na stronę, czyli wykonać GET. A więc musisz zrobić redirect, żeby ten GET się wykonał.
Poczytaj o Post/Redirect/Get.

_addesUser i _editedUser są to publiczne pola statyczne w których przechowuję opis aktualnie edytowanego lub dodawanego użytkownika (przepisuję dane z modelu widoku).

Jesteś pewien, że tego chcesz?
A co jeśli dwóch użytkowników otworzy ten formularz i zacznie dodawać dane?

0
somekind napisał(a):
WojtexProgramista napisał(a):

Czemu mam zastosować RedirectToAction? Przecież chcę wygenerować nowy widok do wprowadzenia danych użytkownika.

No właśnie. A do generowania nowego widoku trzeba wejśc na stronę, czyli wykonać GET. A więc musisz zrobić redirect, żeby ten GET się wykonał.
Poczytaj o Post/Redirect/Get.

_addesUser i _editedUser są to publiczne pola statyczne w których przechowuję opis aktualnie edytowanego lub dodawanego użytkownika (przepisuję dane z modelu widoku).

Jesteś pewien, że tego chcesz?
A co jeśli dwóch użytkowników otworzy ten formularz i zacznie dodawać dane?

OK, dzięki za podpowiedź. Poczytałem i zrozumiałem o co chodzi. Przestawiłem wywołania na RedirectToAction i zaczęło prawidłowo działać. Również pola statyczne przeniosłem do tabeli "Session" (również dzięki za podpowiedź). Mam teraz inny problem. Gdy wywołuję metodę AddConnection by dodać nowe połączenie to nie mam dostępu aktualnie wprowadzonych danych w formularzu. Co skutkuje tym że dodaję nowe połączenie do użytkownika z przed zmiany wartości na stronie (pobieram je z danych zapisanych w tabeli Session). Jak się dobrać do wartości ze zmiennej Model aktualnie wyświetlanej strony? Poza tym jak wywołam stronę dodawania nowego połączenia to podczas wywoływania Submita strony edycji użytkownika w parametrze mam przekazywane dane z przed dodania nowego połączenia. Poniżej mój zmodyfikowany kod kontrolera:


        public ActionResult EditUserId(int userId)
        {
            using (UserDBContext db = new UserDBContext())
            {
                Session["AddedUser"] = null;
                Session["EditedUser"] = db.GetActiveUser(userId);
                return RedirectToAction("EditUser");
            }
        }

        public ActionResult EditUser()
        {
            UserAccount user = Session["EditedUser"] as UserAccount;
            return View("EditUser", GetLayoutName(), user);
        }

        [HttpPost]
        public ActionResult EditUser(UserAccount user)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    using (UserDBContext db = new UserDBContext())
                    {
                        db.SaveUserAccount(user);
                        ModelState.Clear();
                        return View("Index", GetLayoutName(), db.GetUsers());
                    }
                }
            }
            catch (Exception exp)
            {
                ModelState.AddModelError(string.Empty, exp.Message);
            }

            return View("EditUser", GetLayoutName(), user);
        }
        
        public ActionResult AddNewConnection()
        {
            Session["AddedConnection"] = new LocalConnection();
            return RedirectToAction("AddConnection");
        }

        public ActionResult AddConnection()
        {
            LocalConnection conn = Session["AddedConnection"] as LocalConnection;
            return View("AddConnection", GetLayoutName(), conn);
        }

        [HttpPost]
        public ActionResult AddConnection(LocalConnection connection)
        {
            UserAccount editedUser = Session["Editeduser"] as UserAccount;
            if (editedUser != null)
            {
                editedUser.Connections.Add(connection);
                Session["Editeduser"] = editedUser;
                ModelState.Clear();
                return RedirectToAction("EditUser");
            }

            return null;
        }

1 użytkowników online, w tym zalogowanych: 0, gości: 1