3

I am trying to make an online bank website(for learning ASP.NET MVC).I have a class Account

class Account
{
int account_id;
String account_number;
decimal balance;
}

and I have a model for transaction.

 public class MakeTransactionModel
    {
        [Required]
        public String AccountFrom { get; set; }
        [Required]
        public String AccountTo { get; set; }

        public Decimal OrignalBalance { get; set; }
        [Required]
        public Decimal Amount { get; set; }
        [Required]
        public String TransactionFor { get; set; }
    }

Then in controller, i am putting accounts in ViewBag.

ViewBag.account_from = new SelectList(db.Accounts, "account_id", "account_number");

In View, I created a drop down for showing all accounts

@Html.DropDownListFor(u => u.AccountFrom, (SelectList)ViewBag.account_from, htmlAttributes: new { @class = "form-control", @id = "AccountFrom", onchange=@"
                    @Model.OrignalBalance = 1000; // I tried this but did not work
                " })

Now , I am trying to show balance of selected account in an EditorFor

@Html.EditorFor(model => model.OrignalBalance, new { htmlAttributes = new { @id="OrignalBalance", @class = "form-control", disabled = "disabled", @readonly = "readonly" } })

I have all accountsin ViewBag and I am showing that accounts number in drop down (those accounts also have balance in it). I am trying to change value of EditorFor on DropDownFor value change but still unable to do that. I tried to do that using jquery, but i don't know can I use LINQ in jquery

My jquery code is

 <script type="text/javascript">

        $(document).ready(function () {
            $(function () {
                $('#AccountFrom').change(function () {
                    var selectedValue = $('#AccountFrom').text();
                    $('#OrignalBalance').val(@{new BankEntities().Accounts.SingleOrDefault(acc => acc.account_number == $('#AccountFrom').text())});   // I am trying to do this
                });
            });
        }
    )
    </script>

It will be good if i find a good solution to do that, so I can update EditorFor on change event.

Thank you.

3 Answers 3

5

You should make an ajax call and pass the account number and get the amount from the server.

$(function()
{
    $('#AccountFrom').change(function() {
    var accountId= $('#AccountFrom').val();
    var url="@Url.Action("Balance","Account")";
       $.post(url+"?accountNumber="+accountId,function(response){
          if(response.Status==="success")
          {
            $("#OrignalBalance").val(response.Balance);
          }
          else
          {
             alert("Invalid Account");
          }
       });
    });
});

Assuming you have an action method to return the balance

[HttpPost]
public ActionResult Balance(string accountNumber)
{
   //Of course you want to authorize the call
   var db=new BankEntities();
   var a= db.Accounts.FirstOrDefault(x=> x.account_number ==accountNumber);
   if(a!=null)
   {
      return Json( new { Status="success", Balance=a.Balance });
   }
   else
   {
     return Json( new { Status="error"});
   }
}

If you do not wish to make an action method and the ajax way, What you can do is, Create a dictionary of your account number and the balance and pass that as part of your view model and in your razor view, set that to a js object and in the change event you can query the js dictionary to get the value.

Also, I recommend to NOT use ViewBag to transfer data between your action method and your view for rendering the dropdown. You should add a strongly typed property to handle that.

So let's add some new properties to your view model.

public class MakeTransactionModel
{
   // Your other existing properties here

   public Dictionary<string,decimal> AccountBalances { set; get; }   

   // These 2 properties are for rendering the dropdown.
   public int FromAccountId { set; get; }
   public List<SelectListItem> FromAccounts { set; get; }  
}

And in your GET action, fill this property with account number and corresponding balance value.

public ActionResult Transfer()
{
  var vm = new MakeTransactionModel();
  vm.AccountBalances = new Dictionary<string, decimal>();
  // Hard coded for demo. You may read it from your db tables.
  vm.AccountBalances.Add("CHECKING0001", 3450.50M);
  vm.AccountBalances.Add("SAVINGS0001", 4450.50M);

   //load the data for accounts.pls change to get from db
   vm.FromAccounts = new List<SelectListItem>
   {
       new SelectListItem { Value="CHECKING0001", Text="Checking" },
       new SelectListItem { Value="SAVINGS0001", Text="Saving" }
   };

  // to do : Load other properties also
  return View(vm);
}

And in your razor view, serialize this property and set to a js object.

@model MakeTransactionModel
@using(Html.BeginForm())
{
  @Html.DropDownListFor(s=>s.FromAccountId,Model.FromAccounts,"Select")

  @Html.EditorFor(model => model.OrignalBalance, 
     new { @id="OrignalBalance", @class = "form-control",
     disabled = "disabled", @readonly = "readonly" } )
  <input type="submit" />
}
@section Scripts
{
<script>   
var balanceDict = @Html.Raw(Newtonsoft.Json.JsonConvert
                               .SerializeObject(Model.AccountBalances));

$(function () {

    $('#FromAccountId').change(function() {
        var accountId= $('#AccountFrom').val();
        var v = balanceDict[accountId];
        $("#OrignalBalance").val(v);
    });   

});
</script>
}
Sign up to request clarification or add additional context in comments.

4 Comments

thankyou for your response. is there any other way of achieving this. As I dont want to create an action method.
i am trying this code but text is not updating in EditorFor. I debug the code, it is sending the response. but now showing in editor. can you please help me what may be wrong here.
I had a typo in the ajax call. Fixed it. Also added non-ajax solution as well.
actually that jquery work just by changing .html to .val
2

It may not seem like it, but this is pretty broad. Basic rundown, you'll either have to:

  • Serialize all accounts and balances into JSON and store them client-side:

    This is more code than is appropriate here, but you could use JSON.net to get JSON for new BankEntities().Accounts.ToList() (something you should be getting from your controller code, by the way, not in your view), then set a window variable to that in your JavaScript, and call upon that whenever the value changes.

    Untested, but something like:

    var balances = @Html.Raw(JsonConvert.SerializeObject(new BankEntities()
                                                    .Accounts
                                                    // Filter by logged in user
                                                    .ToDictionary(c => c.account_number, c.balance));
    
    $(document).ready(function () {
        $(function () {
            $('#AccountFrom').change(function () {
                var selectedValue = $('#AccountFrom').text();
                $('#OrignalBalance').val(balances[selectedValue]);
            });
        });
    }
    
  • Introduce an API call performed through AJAX to get balances whenever the value changes.

    Shyju beat me to this one, but it's probably a better way to do it, as long as you're comfortable introducing an API element. It's kind of advanced for first learning MVC, but it's not too complicated.

    This is what I'd do in a production application (although I'd do it with Web API), but for just playing, the first option is a little quicker, and probably easier to understand and debug fully if you're just getting started.

The confusion here comes from where code is executed. Your script can't refer to the BankEntities because it's running client-side, as compared to server side.

5 Comments

thank you for your response.do you think is it good to store info on client side.
also can i use that serialize object in selectlist?
@WaqarAhmed Either approach is fine, they're just different. The SelectList is built server-side, so you won't have access to the client-side variable. Although you could pass the same list to be serialized as you do to create the SelectList. That's probably what I'd do, without knowing more about your code.
@WaqarAhmed I think you might have to do something to unescape the dictionary JSON. I think there's something under @Html, but it's been a while since I did anything with MVC.
@WaqarAhmed Found it; I edited my code, but you need to pass that JSON to Html.Raw in order to avoid it being escaped.
1

JQuery knows nothing about LINQ, since it is client based. So, I suggest making an ajax request when the account from gets changed.

for example, in the view, make the ajax call

<script type="text/javascript">

    $(document).ready(function() {

        $('#AccountFrom').change(function() {
            var selectedAccountNumber = $('#AccountFrom option:selected').text();
            $.ajax({
                url: "/Accounts/GetAccountBalance",
                type: "POST",
                dataType: "json",
                data: { accountNumber: selectedAccountNumber },
                success: function (
                    $('#OrignalBalance').val(data.Balance);
                }
            });
        });
    });
</script>

and have the following in the controller (let's say that you have a controller called Accounts)

public ActionResult GetAccountBalance(string accountNumber)
{
    var account = db.Accounts.SingleOrDefault(a => a.account_number == accountNumber);
    // add validation logic for account not exits

    return Json(new { AccountNumber = accountNumber, Balance = account.balance });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.