2

I’m new to MVC and I would like to create a simple view that allows a user to enter some data => submit the form => perform some calculation on the server => and post back a model with the calculated data to the same view. I found a way to make it work, but I’m not sure if this is the best way to do it and what bothers me is that after the submit, all the data from the model properties are visible in the browser address bar : http://localhost:53718/?Number=4&Result=16

Here is the code for a very simplified szenario:

The Model:

public class CalculationModel
{        
    public int Number { get; set; }        
    public int Result { get; set; }
}

The Controler:

public class HomeController : Controller
{
    public ActionResult Index(CalculationModel model)
    {
        return View(model);
    }

    [HttpPost]
    public ActionResult Calculate(CalculationModel model)
    {
        model.Result = model.Number * model.Number;
        return RedirectToAction("Index", "Home", model); 
    }
}

The View:

        @model WebApplication1.CalculationModel

    @{
        ViewBag.Title = "Home Page";
    }

    <h2>Simple Calculation</h2>

    @using (Html.BeginForm("Calculate", "Home", FormMethod.Post)){

        <div class="form-horizontal" data-crypto-conversion-form>
            <div class="form-group">
                <div class="input-group">
                    @Html.EditorFor(model => model.Number, new { htmlAttributes = new { @class = "form-control " } })
                </div>
            </div>

            <div class="form-group">
                <div class="input-group">
                    @Html.EditorFor(model => model.Result, new { htmlAttributes = new { @class = "form-control " } })
                </div>
            </div>

            <div class="form-group">
                <input type="submit" value="Convert" class="btn btn-primary btn-sm submitConversion" />
            </div>

        </div>
    }

I’m not sure if it’s a good idea to do a RedirectToAction from the HttpPost method: return RedirectToAction("Index", "Home", model); - are there any better ways ?

Is there any way to prevent the model property values from displaying in the url / browser address bar ?

Thanks a lot for your help.

robsti
  • 23
  • 3

2 Answers2

2

The RedirectToAction method basically returns a 302 response with the new url in the location header and browser will issue a new GET request to that. When you pass a simple model along with that, it will be converted to querystring values and will be added to the new url in location header.

If you do not want to see the values in querystring, you can return to the Index view with the same view model object from your HttpPost action method. Make sure to clear the model state dictionary so that the new value of Result property will be rendered. You can use the ModelState.Clear() method do so.

[HttpPost]
public ActionResult Calculate(CalculationModel model)
{
    model.Result = model.Number * model.Number;
    ModelState.Clear();
    return View("Index", model); 
}

If you still want to return A RedirectResult response, you can do that, but pass the model data via TempData. Take a look at this post

How do I include a model with a RedirectToAction?

Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Wow, this was fast - I'm really impressed. Thanks a lot, that's exactly what I was looking for. – robsti Oct 30 '17 at 18:04
0

I would change the overall approach and use the same view, because it seems you might want to calculate over and over again. A Get Index method just to display the data to process and/or the result, and then a Post method to do the actual processing.

So, the Controller:

[HttpGet]
public ActionResult Index()
{
    return View();
}

[HttpPost]
public ActionResult Index(CalculationModel model)
{
    model.Result = model.Number * model.Number;
    model.Processed = true;
    return View(model);
}

The model

public class CalculationModel
{
    public int Number { get; set; }
    public int Result { get; set; }
    public bool Processed { get; set; }
    public CalculationModel()
    {
        Processed = false;
    }
}

And the view, which will display the result only after a post.

@model MvcApplication2.Models.CalculationModel
@{
    ViewBag.Title = "Home Page";
}
<h2>Simple Calculation</h2>
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
 <div class="form-horizontal" data-crypto-conversion-form>
        <div class="form-group">
            <div class="input-group">
                @Html.EditorFor(model => model.Number, new { htmlAttributes = new { @class = "form-control " } })
            </div>
        </div>
        @*@(Model.Result)*@
        <div class="form-group">
            <div class="input-group">
                @*@Html.EditorFor(model => model.Result, new { htmlAttributes = new { @class = "form-control " } })*@
                @{if (Model!=null && Model.Processed)
                  {
                    <p>@(Model.Result)</p>
                  }
                }
            </div>
        </div>

        <div class="form-group">
            <input type="submit" value="Convert" class="btn btn-primary btn-sm submitConversion" />
        </div>
    </div>
}
Overlord
  • 2,740
  • 2
  • 18
  • 22