简体   繁体   中英

I am trying to change a string value with a onClick method in a .NET api

So, i have this button that redirects the user to a checkout page. In it I want to define a string from the clicked button. In this case it needs to be "custom"

<button class="btn btn-style" type="submit" id="cOrder">Order</button>
<script>
document.getElementById("cOrder").onclick = function() { 
    @{
        PizzaModel model = new PizzaModel();
        model.Pizza.PizzaName = "Custom";
    }
} 
</sript>

but I keep getting a System.NullReferenceException: 'Object reference not set to an instance of an object.'

this Pizza name is defined on a Model class and I want to use it on the checkout page so the user can see what he ordered

I have this model PizzasModel:

public class PizzasModel
{
    public string PizzaName { get; set; }
    public float PizzaPrice { get; set; }
    public string Adress { get; set; }
    public string Payment { get; set; }
    public bool Cheese { get; set; }
    public bool Mushroom { get; set; }
    public bool Pepperoni { get; set; }
    public bool Pinaple { get; set; }
    public bool Sauce { get; set; }
    public bool Tomato { get; set; }
}

which is consumed by the PizzaModel (Pizza.cshtml) generated by .NET

public class PizzaModel : PageModel
{
    [BindProperty]
    public PizzasModel Pizza { get; set; }
    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
        return RedirectToPage("/Checkout/Checkout", new {Pizza.PizzaName, Pizza.PizzaPrice});
    }
}

The OnPost method uses the form that my button is inserted

<form method="post">

                  <div class="toppigns-items">
                      <label for="Ch">Cheese</label>
                      <input class="check" type="checkbox" id="Ch" name="topping" value="Ch" asp-for="Pizza.Cheese">
                  </div>
                  <div class="toppigns-items">
                       <label for="Mu">Mushroom</label>
                       <input class="check" type="checkbox" id="Mu" name="topping" value="Mu" asp-for="Pizza.Mushroom">
                  </div>
                  <div class="toppigns-items">
                       <label for="Pe">Pepperoni</label>
                       <input class="check" type="checkbox" id="Pe" name="topping" value="Pe" asp-for="Pizza.Pepperoni">
                  </div>
                  <div class="toppigns-items">
                      <label for="Pi">Pinaple</label>
                      <input class="check" type="checkbox" id="Pi" name="topping" value="Pi" asp-for="Pizza.Pinaple">
                  </div>
                  <div class="toppigns-items">
                      <label for="Sa">Sauce</label>
                      <input class="check" type="checkbox" id="Sa" name="topping" value="Sa" asp-for="Pizza.Sauce">
                  </div>
                  <div class="toppigns-items">
                      <label class="lCheck" for="To">Tomato</label>
                      <input type="checkbox" id="To" name="topping" value="To" asp-for="Pizza.Tomato">
                  </div>
                  <hr />
                  <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
                  <button class="btn btn-style" type="submit" id="cOrder">Order</button>                 
              </form>

And finally is used on my checkout page, where will be displayed some atrributes

<div>
    <p>1 @Model.PizzaName</p>
    <p>Total: U$@Model.PizzaPrice</p>
</div>

What I am trying to do is set PizzaName by the button clicked

The first issue, the one that causes the exception you're getting, is because the PizzaModel.Pizza property isn't initialized, so it has the default value of null . When you try to set a property using model.Pizza.PizzaName = "Custom";there is no object for the value to apply to.

To fix this you need to create and assign a instance of PizzasModel to the Pizza property. You can either do this in the PizzaModel class or during object creation.

Option one:

public class PizzaModel : PageModel
{
    [BindProperty]
    public PizzasModel Pizza { get; set; } = new PizzasModel();
    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
        return RedirectToPage("/Checkout/Checkout", new {Pizza.PizzaName, Pizza.PizzaPrice});
    }
}

Option two (combining initialization of the PizzaName property):

PizzaModel model = new PizzaModel 
{ 
    Pizza = new PizzasModel
    {
        PizzaName = "Custom",
    }
};

The next problem is that you can't mix javascript and C# code that way. C# code in @{ } blocks will execute on the server during page generation, before the HTML for the page is transmitted to the client. The object you create in that code are server-side only and not accessible to the client in any way, and they will be elegible for garbage collection as soon as page generation completes.

On the client side your script looks like this:

<script>
document.getElementById("cOrder").onclick = function() { 
} 
</sript>

If you want things to happen on the client you need to either write them as javascript or write some dynamic page code that interfaces with C# code on the server side. There are various libraries around that facilitate this kind of thing depending on what you're after, but they all run server side with all of the communications delays and so on. Better to handle the client-side stuff directly unless it actually requires server-side functionality.

In this case it seems like you're wanting to browse to a new page. In that case all you need is a way to pass the appropriate data to the server during the page fetch. For small amounts of non-sensitive data you can just add it to the query string - https://server/page?PizzaName=Custom for instance. For more complex data a form is often simpler:

<form method="post" id="theForm" action="page" style="display:none">
  <input asp-for="Pizza.PizzaName" type="hidden" id="PizzaName" />
  <input asp-for="Pizza.Cheese" type="hidden" />
  <input asp-for="Pizza.Pepperoni" type="hidden" />
</form>

<script type="text/javascript">
  document.getElementById("cOrder").onclick = function() { 
    document.getElementById("PizzaName").value = "Custom";
    document.getElementById("theForm").submit();
  }
</script>

In the OnPost() method the Pizza property will be filled with values from the form, but you'll want to initialize it in OnGet() or potentially face the wrath of the NullReferenceException .

There are numerous variations on the theme, including constructing the form's input elements during click and so on. Or just go ahead and put an actual visible form in the page and post from that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM