MVC Razor Hidden input and passing values
Asked Answered
T

6

26

I am pretty sure I am doing something wrong here. I have been developing a web app using MVC and Razor and I never thought of using the form element. Now so much has already been done with master pages and sub pages that it means restructuring most of our code in order to use form element and the would result in multiple form elements on a page.

That aside, in Asp.Net if I wanted to access any control in the C# code behind I could just give it an ID="SomeID" and a RUNAT="SERVER". Then in my code behind I could set its value and properties.

When I do this in Razor, I use lines like:

 <input id="hiddenPostBack" runat="server" type="hidden" />

Why can't I access this in the controller? I want to detect a postback and set the value to false if it is the first time the page loads, and if not, then set the value to true. Then based on this, I will read it either server side or client side and do something.

My real question is, how do I "do something" both server side and client side given that I don't have a form element. I was under the impression that if I wanted to pass values from client to server and back, the easiest way to do this is with a hidden input. But I am just not getting how to accomplish this with MVC3 and razor.

Telephonic answered 4/7, 2012 at 8:51 Comment(1)
There's no managed "Postback" in MVC. You need to use javascript to manage actions on client side...Unilobed
S
46

A move from WebForms to MVC requires a complete sea-change in logic and brain processes. You're no longer interacting with the 'form' both server-side and client-side (and in fact even with WebForms you weren't interacting client-side). You've probably just mixed up a bit of thinking there, in that with WebForms and RUNAT="SERVER" you were merely interacting with the building of the Web page.

MVC is somewhat similar in that you have server-side code in constructing the model (the data you need to build what your user will see), but once you have built the HTML you need to appreciate that the link between the server and the user no longer exists. They have a page of HTML, that's it.

So the HTML you are building is read-only. You pass the model through to the Razor page, which will build HTML appropriate to that model.

If you want to have a hidden element which sets true or false depending on whether this is the first view or not you need a bool in your model, and set it to True in the Action if it's in response to a follow up. This could be done by having different actions depending on whether the request is [HttpGet] or [HttpPost] (if that's appropriate for how you set up your form: a GET request for the first visit and a POST request if submitting a form).

Alternatively the model could be set to True when it's created (which will be the first time you visit the page), but after you check the value as being True or False (since a bool defaults to False when it's instantiated). Then using:

@Html.HiddenFor(x => x.HiddenPostBack)

in your form, which will put a hidden True. When the form is posted back to your server the model will now have that value set to True.

It's hard to give much more advice than that as your question isn't specific as to why you want to do this. It's perhaps vital that you read a good book on moving to MVC from WebForms, such as Steve Sanderson's Pro ASP.NET MVC.

Scimitar answered 4/7, 2012 at 9:10 Comment(2)
I agree, I do need a good book. However we are at first release and just want to get something out the door asap so, as explained, rewriting the pages to use forms properly is not practical at the moment, but later it will be definite. What you have suggested is better than what I have seen to some degree, but it still takes the approach of a model and controller/actionresult for each control on a view page. I am posting back using drop down combo boxes and click events of check boxes or radios, and the occasional button. But javascript handles the redirection. Thanks for your suggestions.Telephonic
I know this is a very old answer, but I'm still getting points for it, so it's clearly still of some interest. I just wanted to add that you need to make sure the setter for your "HiddenPostBack" value is set to be public, otherwise it won't be set by the model binder. This caught me out yesterday. Eg, public bool HiddenPostBack { get; set; }Scimitar
A
10

If you are using Razor, you cannot access the field directly, but you can manage its value.

The idea is that the first Microsoft approach drive the developers away from Web Development and make it easy for Desktop programmers (for example) to make web applications.

Meanwhile, the web developers, did not understand this tricky strange way of ASP.NET.

Actually this hidden input is rendered on client-side, and the ASP has no access to it (it never had). However, in time you will see its a piratical way and you may rely on it, when you get use with it. The web development differs from the Desktop or Mobile.

The model is your logical unit, and the hidden field (and the whole view page) is just a representative view of the data. So you can dedicate your work on the application or domain logic and the view simply just serves it to the consumer - which means you need no detailed access and "brainstorming" functionality in the view.

The controller actually does work you need for manage the hidden or general setup. The model serves specific logical unit properties and functionality and the view just renders it to the end user, simply said. Read more about MVC.

Model

public class MyClassModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string MyPropertyForHidden { get; set; }
}

This is the controller aciton

public ActionResult MyPageView()
{
    MyClassModel model = new MyClassModel(); // Single entity, strongly-typed
    // IList model = new List<MyClassModel>(); // or List, strongly-typed
    // ViewBag.MyHiddenInputValue = "Something to pass"; // ...or using ViewBag

    return View(model);
}

The view is below

//This will make a Model property of the View to be of MyClassModel
@model MyNamespace.Models.MyClassModel // strongly-typed view
// @model IList<MyNamespace.Models.MyClassModel> // list, strongly-typed view

// ... Some Other Code ...

@using(Html.BeginForm()) // Creates <form>
{
    // Renders hidden field for your model property (strongly-typed)
    // The field rendered to server your model property (Address, Phone, etc.)
    Html.HiddenFor(model => Model.MyPropertyForHidden); 

    // For list you may use foreach on Model
    // foreach(var item in Model) or foreach(MyClassModel item in Model)
}

// ... Some Other Code ...

The view with ViewBag:

// ... Some Other Code ...

@using(Html.BeginForm()) // Creates <form>
{
    Html.Hidden(
        "HiddenName",
        ViewBag.MyHiddenInputValue,
        new { @class = "hiddencss", maxlength = 255 /*, etc... */ }
    );
}

// ... Some Other Code ...

We are using Html Helper to render the Hidden field or we could write it by hand - <input name=".." id=".." value="ViewBag.MyHiddenInputValue"> also.

The ViewBag is some sort of data carrier to the view. It does not restrict you with model - you can place whatever you like.

Admonitory answered 4/7, 2012 at 9:41 Comment(3)
Thats why I refer to Razor examples.Admonitory
@Francis doesn't know the difference between MVC and Webforms. Razor or ASPX view engine doesn't matter because he could use ASPX view engine in MVC and still face exactly the same problem.Akilahakili
I have come across this idea a lot. However, I find it hard to beleive it practical that I should create a new model and/or controller action result for every control on my view page. Even if it were possible to have multiple controllers for a page or action results for a control on a page (as far as I know it is not but I am open to being wrong), how do I go about calling that action result in the relevant controller. I am confused at this approach, however thank you for your answer.Telephonic
T
1

As you may have already figured, Asp.Net MVC is a different paradigm than Asp.Net (webforms). Accessing form elements between the server and client take a different approach in Asp.Net MVC.

You can google more reading material on this on the web. For now, I would suggest using Ajax to get or post data to the server. You can still employ input type="hidden", but initialize it with a value from the ViewData or for Razor, ViewBag.

For example, your controller may look like this:

public ActionResult Index()
{
     ViewBag.MyInitialValue = true;
     return View();
} 

In your view, you can have an input elemet that is initialized by the value in your ViewBag:

<input type="hidden" name="myHiddenInput" id="myHiddenInput" value="@ViewBag.MyInitialValue" />

Then you can pass data between the client and server via ajax. For example, using jQuery:

$.get('GetMyNewValue?oldValue=' + $('#myHiddenInput').val(), function (e) {
   // blah
});

You can alternatively use $.ajax, $.getJSON, $.post depending on your requirement.

Technique answered 4/7, 2012 at 9:9 Comment(2)
I understand your suggestion is not the standard MVC way of doing things. But I am initially looking for a quick and dirty approach and I will give your example more taught. Later when time allows I will reprogram my solution to a better standard but for now I need to get it out the door. I am not sure yet, but this may have been the answer I was looking for.Telephonic
Give it a try and see. I've been doing this for some other stuff, but for your purposes it could be feasible as well. It isn't necessarily the best practice, but MVC doesn't forbid employing Ajax nonetheless. Just don't use this technique extensively.Technique
W
0

First of all ASP.NET MVC does not work the same way WebForms does. You don't have the whole runat="server" thing. MVC does not offer the abstraction layer that WebForms offered. Probabaly you should try to understand what controllers and actions are and then you should look at model binding. Any beginner level tutorial about MVC shows how you can pass data between the client and the server.

Wilks answered 4/7, 2012 at 9:4 Comment(2)
You can use ASP Forms in MVC, I think. The View Engine choice is between Razor CSHTML or ASP Web Forms.Admonitory
You can indeed, but have you noticed such forms dont have a code behind anymore. :-) (understandable as the controller is the new code behind). Thanks for your answer.Telephonic
R
0
@* Using style attribute to hide *@
<input type="text" id="inputField" style="display: none;" />
<label for="inputField" style="display: none;">Hidden Label</label>

@* Using hidden attribute to hide *@
<input type="text" id="inputField" hidden />
<label for="inputField" hidden>Hidden Label</label>
Repand answered 27/2 at 17:0 Comment(0)
R
-1

You are doing it wrong since you try to map WebForms in the MVC application.

There are no server side controlls in MVC. Only the View and the Controller on the back-end. You send the data from server to the client by means of initialization of the View with your model.

This is happening on the HTTP GET request to your resource.

[HttpGet]
public ActionResult Home() 
{
  var model = new HomeModel { Greeatings = "Hi" };
  return View(model);
}

You send data from client to server by means of posting data to server. To make that happen, you create a form inside your view and [HttpPost] handler in your controller.

// View

@using (Html.BeginForm()) {
  @Html.TextBoxFor(m => m.Name)
  @Html.TextBoxFor(m => m.Password)
}

// Controller

[HttpPost]
public ActionResult Home(LoginModel model) 
{
  // do auth.. and stuff
  return Redirect();
}
Redbird answered 4/7, 2012 at 9:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.