Output Model to MVC View

I'm using Visual Studio 2017 with C#.
I want a user to input some letters into a textbox.  A model maps each letter to a number and returns the total.  how can I display the result (Total variable in the model) in a text area in the same view?

Home Controller
public ActionResult Cards()
        {
            return View();
        }
        public ActionResult Cards(CardModel C)
        {
            C.GetScore(C.Deck);
            return View();
        }

Open in new window


Cards View
@{
    ViewBag.Title = "Cards";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<h2>Cards</h2>

    <h2>Please enter a number</h2>

      First name: <input type="text" name="Deck"><br>
      <textarea id="TextArea1" rows="2" cols="20"></textarea>
    <input type="submit" value="Submit">

Open in new window


Model
 public class CardModel
    {
        public string Deck { get; set; }
        public int GetScore(string s)
        {
            int score = 0;
            int totalScore = 0;
            string individualCard = "";
            //loop through each letter in string and convert to a number.
           return Total
}
}

Open in new window

AlHal2Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kelvin McDanielSr. DeveloperCommented:
First, update your controller to return the Model so it will be bound to the View.

public ActionResult Cards()
{
        return View();
}

public ActionResult Cards(CardModel C)
{
        C.GetScore(C.Deck);
        return View(C);
}

Open in new window


Next, add an int property to CardModel that will be used to show the result of the GetScore() function call. For the sake of discussion I've added one named Result. Notice that I didn't change the return type of GetScore(). However, in this example it could be void instead of returning int.

public class CardModel
{
        public string Deck { get; set; }

        // new property
        public int Result { get; set;}

        public int GetScore(string s)
        {
            int score = 0;
            int totalScore = 0;
            string individualCard = "";
            //loop through each letter in string and convert to a number.

           // set Result equal to the Total
           Result = totalScore;
           return totalScore;
        }
}

Open in new window


Finally, update your View to use the CardModel class as its bound Model. Also, set the View to show the value of the new property Result in the textarea element.

@model CardModel
ViewBag.Title = "Cards";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<h2>Cards</h2>

    <h2>Please enter a number</h2>

      First name: <input type="text" name="Deck"><br>
      <textarea id="TextArea1" rows="2" cols="20">@Model.Result</textarea>
    <input type="submit" value="Submit">

Open in new window


And you should be good to go. I did this from memory on my phone so you might have to tweak it a bit. For example, make sure your namespaces are correct for the CardModel reference in the View. Also, for the code you've provided you need to add a Form element. Of course you could use JavaScript but I don't see any evidence of that being used here.
AlHal2Author Commented:
This line of code

<textarea id="TextArea1" rows="2" cols="20">@Model.Result</textarea>

Open in new window


gives this error when I start the project.

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=App_Web_apmgbbnv
  StackTrace:
   at ASP._Page_Views_Home_Cards_cshtml.Execute() in D:\OneDrive\Documents\Tests\BT\WebApplication1\WebApplication1\Views\Home\Cards.cshtml:line 41

Open in new window


This is the controller code.
        [HttpGet]
        public ActionResult Cards()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Cards(CardModel C)
        {
            C.GetScore(C.Deck);
            return View(C);
        }

Open in new window

I've added the result variable to the model.
Kelvin McDanielSr. DeveloperCommented:
Please post the entire View code where that line exists.
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

kaufmed   (⌐■_■)Shot Through the Heart, and You're to Blame, You Give vars a Bad NameCommented:
You're not passing a model in your GET version.
AlHal2Author Commented:
Hi Kelvin,

The user hasn't entered any information when the GET version is called, so I'm not sure which model to pass.

Hi Kaufmed,

Here is the view.

@model WebApplication1.Models.CardModel
ViewBag.Title = "Cards";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<h2>Cards</h2>

<h2>Please enter a number</h2>

      First name: <input type="text" name="Deck"><br>
<textarea id="TextArea1" rows="2" cols="20">@Model.Result</textarea>
<input type="submit" value="Submit">

Open in new window

kaufmed   (⌐■_■)Shot Through the Heart, and You're to Blame, You Give vars a Bad NameCommented:
Pass a new, empty model.

return View(new WebApplication1.Models.CardModel());

Open in new window

AlHal2Author Commented:
Thanks Kaufmed.  I'm no longer getting an error message, but nothing happens when I click submit.  I expected it to call this method in the home controller.

        [HttpPost]
        public ActionResult Cards(CardModel C)
        {
            C.GetScore(C.Deck);
            return View(C);
        }

Open in new window


In _Layout.cshtml I've added the Cards view, so it appears as one of the options.

<div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                    <li>@Html.ActionLink("Cards", "Cards", "Home")</li>
                </ul>
            </div>

Open in new window

kaufmed   (⌐■_■)Shot Through the Heart, and You're to Blame, You Give vars a Bad NameCommented:
Where is the code for your form and your submit button?
AlHal2Author Commented:
Here is the controller code.
        public ActionResult Cards(CardModel C)
        {
            try
            {
                C.GetScore(C.Deck);
                Models.CardModel NewModel = new Models.CardModel { Deck = C.GetScore(C.Deck).ToString() };
                return View("Score", NewModel);
                //return View(C);
            }
            catch (Exception ex)
            {
                return View("Error", ex.Message);
            }

        }

Open in new window


Here is the score view
@model WebApplication1.Models.CardModel

<div>
    <h4>CardModel</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @*@Html.DisplayNameFor(model => model.Deck)*@
            Score: 
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Deck)
        </dd>

    </dl>
</div>
@*<p>
    @Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ }) |
    @Html.ActionLink("Back to List", "Index")
</p>*@

Open in new window


Here is the error view.  I want to replace the words invalid deck with the error message.

Invalid Deck

Here is the model.
using System;
namespace WebApplication1.Models
{
    public class CardModel
    {
        public int Result { get; set; } 
        public string Deck { get; set; }
        public string ErrorMessage { get; set; }
        public int GetScore(string s)
       
        {
  
                int score = 0;
                int totalScore = 0;
                string individualCard = "";
                bool oneJokerFound = false;
                bool twoJokersFound = false;
                int number;
                if (s == null)
                {
                    return 0;
                }
                else if (s == "")
                {
                    return 0;
                }
                for (int i = 2; i < s.Length; i += 3)
                {
                    if (s.Substring(i, 1) != ",")
                    {
                        throw new Exception("Deck must consist of two digit card followed by comma");
                    }
                }
                s = s.Replace(",", "");
                do
                {
                    if (int.TryParse(s.Substring(0, 1), out number))
                    {
                        score = int.Parse(s.Substring(0, 1));
                    }
                    else if (s.Substring(0, 1) == "T")
                    {
                        score = 10;
                    }
                    else if (s.Substring(0, 1) == "J" && s.Substring(0, 2) != "JR")
                    {
                        score = 11;
                    }
                    else if (s.Substring(0, 1) == "Q")
                    {
                        score = 12;
                    }
                    else if (s.Substring(0, 1) == "K")
                    {
                        score = 13;
                    }
                    else if (s.Substring(0, 1) == "A")
                    {
                        score = 14;
                    }
                    else if (s.Substring(0, 2) == "JR")
                    {
                        if (twoJokersFound == true)
                        {
                            throw new Exception("More than two jokers");
                            //totalScore = 0;
                            //break;
                        }
                        score = 0;
                        if (oneJokerFound == true)
                        {
                            oneJokerFound = false;
                            twoJokersFound = true;
                        }
                        else
                        {
                            oneJokerFound = true;
                            twoJokersFound = false;
                        }
                    }
                    else
                    {
                        throw new Exception("Invalid card");
                        //totalScore = 0;
                        //break;
                    }
                    switch (s.Substring(1, 1))
                    //switch (s.Substring(i + 1, 1))
                    {
                        case "C":
                            break;
                        case "D":
                            score = score * 2;
                            break;
                        case "H":
                            score = score * 3;
                            break;
                        case "S":
                            score = score * 4;
                            break;
                        case "R":
                            score = 0;
                            break;
                        default:
                            throw new Exception("Invalid card");
                            //totalScore = 0;
                            //break;
                    }
                    totalScore += score;

                    individualCard = s.Substring(0, 2);
                    //individualCard = s.Substring(i, 2);
                    //if (individualCard != "JR")
                    //{
                    s = s.Remove(0, 2);
                    //}

                    s.Replace(",,", ",");
                    if (s.Length > 1 && s.Substring(0, 1) == ",")
                    {
                        s = s.Remove(0, 1);
                    }
                    if (s.Contains(individualCard) && individualCard != "JR")
                    {
                        throw new Exception("Duplicate card " + individualCard);
                        //totalScore = 0;
                        //break;
                    }

                } while (s.Length > 0);
                if (oneJokerFound == true)
                    totalScore = totalScore * 2;
                else if (twoJokersFound == true)
                {
                    totalScore = totalScore * 4;
                }
                return totalScore;
   
        }
    }
}

Open in new window

Kelvin McDanielSr. DeveloperCommented:
As @Kaufmed has alluded to, this won't do anything without an HTML Form element or JavaScript to push the POST to your server endpoint. I've taken the liberty of revising your view to be more modern and use the Helpers since you don't appear to need more flexibility for this example.

@model WebApplication1.Models.CardModel
ViewBag.Title = "Cards";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<h2>Cards</h2>

<h2>Please enter a number</h2>

@using(Html.BeginForm("Cards", "Home", FormMethod.Post)) 
{
	First name: @Html.TextboxFor(m => m.Deck)<br>
	@Html.TextAreaFor(m => m.Result, 2, 20)
	<input type="submit" value="Submit">
}

Open in new window


Note the TextAreaFor helper on line 14; you might run into some issues if you have needs other than simply binding to this element. If that's the case, take a look at this post for some suggestions on what to do.
AlHal2Author Commented:
I'm getting these error messages from your code.
Error      CS1061      'HtmlHelper<CardModel>' does not contain a definition for 'TextboxFor' and no extension method 'TextboxFor' accepting a first argument of type 'HtmlHelper<CardModel>' could be found (are you missing a using directive or an assembly reference?)
Error      CS1501      No overload for method 'TextAreaFor' takes 3 arguments      

However, this code works.
@using (Html.BeginForm("Cards", "Home"))
    {
        <input type="text" name="Deck"><br>
    <textarea id="TextArea1" rows="2" cols="20">@Model.Result</textarea>

        <input type="submit" value="Submit">
    }

Open in new window


I'm also trying to handle errors.  My controller method looks like this.  How should I amend the Cards view to display the exception message.

        [HttpPost]
        [HandleError]
        public ActionResult Cards(CardModel C)
        {
            string exmsg = "";
            try
            {
                C.GetScore(C.Deck);
                Models.CardModel NewModel = new Models.CardModel { Deck = C.GetScore(C.Deck).ToString() };
                return View("Score", NewModel);
                //return View(C);
            }
            catch (Exception ex)
            {
                exmsg = ex.Message;
                ModelState.AddModelError("General error", exmsg);
                return View();

            }

        }

Open in new window

Kelvin McDanielSr. DeveloperCommented:
I really want to help, but it's clear that you're just getting started and haven't gotten the basics fundamentals of ASP.NET MVC down yet.
- @Html.TextboxFor should be @Html.TextBoxFor. IntelliSense should have told you that.
- @Html.TextAreaFor --> just pass a null for the 4th parameter. IntelliSense and the link I provided should have told you that.

A few things to consider:
- These Q&A forums on EE assume that you've got those fundamentals and just need a nudge in the right direction.
- What you're asking for is a bit beyond the scope of the help we can efficiently provide in the open forums here on EE.
- This back and forth trial and error is really frustrating for everyone -- to give you the level of support you're really asking for, we would need to download and work directly in your VS solution.

Please note that at any time, you can, however, engage with one (or more) of the Experts that accept Live sessions. Typically, they'll be able to assist in the level of detail that you need. This is not a plug for myself because I don't do EE Gigs.

Good luck!

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AlHal2Author Commented:
Thanks both.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.