MVC & ASP.Net Web Form : Viewstate? - asp.net

I have used ASP.Net Webforms. I am currently learning MVC, and I have read that ASP.NET MVC–generated pages don’t contain any View State data.
Can someone explain what is the substitute for viewstate in MVC?
How come they eliminated viewstate? As controls also have viewstate, what's the alternative in that case?

In webforms, the first page load is distinguished by using IsPostback property and server controls are basically initialized with data or initial values in Page_Load event. These initial settings are persisted on subsequent post back events for the page. As you may already know, all this is accomplished by viewstate which is basically a hidden variable that contains state of all server controls on the page and gets posted back for each postback event.
MVC doesn't have this mechanism and is completely stateless i.e, we need to manually assign values of controls for each request. For ex:
In Web forms
ASPX page:
<asp:TextBox id="txtName" runat="server"/>
<asp:Button id="btnSubmit" Text="submit" onclick = "btnSubmit_click" />
Code behind
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostback)
{
txtName.Text = "test1";
}
}
protected void btnSubmit_click(object sender, EventArgs e)
{
//some code
}
Enter a value and click on submit button, the value gets persisted event after postback due to viewstate.
In MVC
View
#using(Html.BeginForm()){
<input id="Name" type="text" name="Name"/>
<input type="submit" value="submit" />
}
Controller
[HttpPost]
public ActionResult Index(FormCollection values)
{
return View();
}
Enter a value and click on submit button, the value is not persisted across postback since there is no such persistence mechanism. So we need to achieve it manually
View
#using(Html.BeginForm()){
<input id="Name" type="text" name="Name" value="#ViewBag.Name"/>
<input type="submit" value="submit" />
}
Controller
[HttpPost]
public ActionResult Index(FormCollection values)
{
ViewBag.Name = values["name"];
return View();
}
Note: I have used ViewBag only to show an example, ideally we need to pass viewmodel from controller.
Additional Inputs
Apart from its role of persisting state, ViewState can also be used to store values, say for ex: ViewState["test"] = objectoranyothervalue. In MVC, there are other techniques for state management like ViewBag, ViewData and TempData but difference is they don't get posted back to server like ViewState. They are used to just pass data from controller to view.

Related

html transferring values in button click

I have a html application with Textbox and a button. (static application)
I need to transfer the textbox value on the button click,
which will take me to another asp.net application.
(Where I can retrieve that in query string) is that possible?
2 applications are in different servers.
make the method of your form get and and the action of the form the url of the other website you want to hit eg
<form action="http://www.google.co.uk" method="get">
<input type="text" name="test" />
</form>
when submitted will post to http://www.google.co.uk?test=ValueOfInput
EDIT
Just noticed you are using asp.net - this is not static html! As your have an asp button you can add a button click event so your code looks like this:
<input ID="btnsrch" type="button"value="Search" runat="server" onclick="btnsrch_click" />
then in your corresponding cs file you can add the following function:
protected void btnsrch_click (object sender, EventArgs e)
{
Response.Redirect(string.Format("http://www.urltogoto.com?variable={0}", txtsrch.Text));
}
Yes this is possible.
You can give a postback url and can get the value in request object over their.

How to verify whether HTML controls exist from code behind

I have an asp.net form.
But the controls inside the form at 1 textbox and 2 dropdown lists as a row.
And there is a "plus" and "minus" buttons for users to add in and delete the rows.
When the form is submitted, I will grab the values from those controls by using Request.Form["ControlName"]
But I need to confirm whether that ["ControlName"] exists.
I can put that piece of code in try catch to confirm like this
for(int a=1;a<10;a++)
{
try
{
Response.Write(Request.Form["ControlName"+a.ToString()]);
}
catch {}
}
By doing this, the controls which don't exist will be catched by catch statement in theory.
But I am trying to use another method to do the checking like FindControl("ServerControlID")
But that one is for the server controls only.
My front code will be something like this
<input type="text" id="txt1" name="txt1"/>
<input type="text" id="txt2" name="txt2"/>
<input type="text" id="txt4" name="txt3"/>
NOTE : I cannot add in runat="server". If so, I can use FindControl()
If you want to access a control on server side (code behind), than that control must be a server control or even an html control but with runat = "server" attribute, by introducing you can access the HTML control.
<input type="text" id="txt1" name="txt1" runat = "server"/>
You could use the NameValueCollection returned by Request.Form.AllKeys.
This returns an IEnumerable
Use Linq to check it as follows:
for(int a=1;a<10;a++)
{
var paramName = "ControlName"+a.ToString();
if(Request.Form.AllKeys.Contains(paramName ))
{
Response.Write(Request.Form[paramName ]);
}
else
{
//key not present
}
}

UpdatePanel resetting object to inital state

I have an application that I am currently writing that works by iterating through nodes, and then updating the page with the information of the current node. I have an UpdatePanel in the page which contains a label, textbox, and a button. The label lists the currently available children of the current node, the user enters in which child they want to go to into the textbox, and then hits the submit button. I set the new value of the node in the submit button's event handler.
Here's my problem: Every time I enter in which node I want to navigate to, the object resets its value to the value it was initially initialized to. I have even put this same code into a Windows Form to validate that it's working correctly to iterate through my tree, and it works as it should, so I know my problem is AJAX-related.
This is the first app that I have written using AJAX, so I am still in the process of learning how it works. Any help would be greatly appreciated. I have Googled and searched SO through and through.
Here is the HTML:
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="question" runat="server" Text=""></asp:Label>
<br />
<asp:TextBox ID="answer" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Submit" runat="server" Text="Submit" onclick="Submit_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
And the C#:
protected void Submit_Click(object sender, EventArgs e)
{
int ans = int.Parse(answer.Text);
if (!current.ChildIDs.Contains(ans))
{
return;
}
current = tree.Node(ans);
question.Text = current.Question;
}
current is the current node, which has a public ArrayList of all of its children's IDs. tree is the NodeTree I have; calling Node just returns the new node. Both current and Tree get initialized in the Page_Load event, and that only fires once (when the page is first loaded).
It's really pretty simply code; I'm just having difficulty understanding why the AJAX isn't working correctly.
I have even put this same code into a
Windows Form to validate that it's
working correctly to iterate through
my tree, and it works as it should, so
I know my problem is AJAX-related.
It sounds like you're expecting ASP.NET to remember what the object current is between requests, since that's how Windows forms applications work.
Web applications are stateless - after each request, ASP.NET discards all your variables. To access the variable during a subsequent request, you have to either:
1) Send enough data with the request to reconstruct the variable. You can do this using a querystring parameter or an HTML form value (the hidden fields another response mentioned).
2) Save the variables in a Session store (which can be in-memory or backed by a database).
3) Store the value in a coookie.
Of these three, it's easiest to show you how to use Session, given what you've shared in your question. However, beware: session has its risks - by default, ASP.NET session objects are stored in-memory, and it's a potential security hazard. But here's how you should be able to get your application to work.
// In your Page_Load code that initializes your 'current' variable
// When the user first requests the page, create a new Node
if (! this.IsPostBack)
{
Node current = new Node(); //
Session("currentNode") = current;
}
// When the user clicks a button on the page (posts), use the
// node in session instead
else
{
current = Session("currentNode");
}
When you update non-form elements in the browser (labels, literals, etc.), .NET is unable to see any of the changes you've made.
Try adding a hidden input for each label that records the new value. Then within the method you have wired up to the button's OnClick event, do something like this:
myLabel.Text = myHiddenInput.value;
I think you just need to tell the updatepanel to update itself. Try this:
protected void Submit_Click(object sender, EventArgs e)
{
int ans = int.Parse(answer.Text);
if (!current.ChildIDs.Contains(ans))
{
return;
}
current = tree.Node(ans);
question.Text = current.Question;
UpdatePanel.Update();
}

How do I get many property values from View to Presenter in WebFormsMvp?

What is the best way to get a number of property values of a business object from the View to the Presenter in a WebFormsMvp page?
Bearing in mind this issue with DataSources.
Here is what i propose:
The scenario is, I have a business object called Quote which i would like to load form the database, edit and then save. The Quote class has heaps of properties on it. The form is concerned with about 20 of these properties. I have existing methods to load/save a Quote object to/from the database. I now need to wire this all together.
So, in the View_Load handler on my presenter i intend to do something like this:
public void View_Load(object sender, EventArgs e)
{
View.Model.Quote = quoteService.Read(quoteId);
}
And then bind all my controls as follows:
<asp:TextBox ID="TotalPriceTextBox" runat="server"
Text="<%# Model.Quote.TotalPrice %>" />
All good, the data is on the screen.
The user then makes a bunch of changes and hits a "Submit" button. Here is where I'm unsure.
I create a class called QuoteEventArgs exposing the 20 properties the form is able to edit. When the View raises the Submit button's event, I set these properties to the values of the controls in the code behind. Then raise the event for the presenter to respond to. The presenter re-loads the Quote object from the database, sets all the properties and saves it to the database.
Is this the right way to do this? If not, what is?
"A nicer way" (/alternative) is to make use of the 2-way binding, therefore what will be passed back to the Presenter for processing will be your Quote object.
This can be achieved through the use of an asp:FormView in conjunction with the mvp:PageDataSource that specifies an UpdateMethod and the Bind() method.
The WebFormsMVP sample project demonstrates this via the 'EditWidgetControl', including the methods required on the View code-behind file.
As an option your view can simply implement only the EditItemTemplate for asp:FormView making use of DefaultMode="Edit" on the FormView.
Sample Structure:
<asp:FormView DataSourceID="theSource" DefaultMode="Edit">
<EditItemTemplate>
<fieldset>
<asp:TextBox id="totp" value='<%# Bind("TotalPrice") %>' runat="server" />
</fieldset>
</EditItemTemplate>
</asp:FormView>
<mvp:PageDataSource ID="theSource" runat="server"
DataObjectTypeName="Your.NameSpace.Quote"
UpdateMethod="UpdateQuote">
</mvp:PageDataSource>
Code-behind:
public void UpdateQuote(Quote q, Quote ori)
{
OnUpdatingQuote(q, ori);
}
public event EventHandler<UpdateQuoteEventArgs> UpdatingQuote;
private void OnUpdatingQuote(Quote q, Quote ori)
{
if (UpdatingUserGroup != null)
{
UpdatingUserGroup(this, new UpdateQuoteEventArgs(q, ori));
}
}
How to use the GridView inside a FormView.
Because I have list to populate the grid in a entity.

Implementing a search page using url parameters in ASP.NET and ASP.NET MVC

Let's say I have a search page called Search.aspx that takes a search string as a url parameter ala Google (e.g. Search.aspx?q=This+is+my+search+string).
Currently, I have an asp:TextBox and an asp:Button on my page. I'm handling the button's OnClick event and redirecting in the codebehind file to Search.aspx?q=
What about with ASP.NET MVC when you don't have a codebehind to redirect with? Would you create a GET form element instead that would post to Search.aspx? Or would you handle the redirect in some other manner (e.g. jQuery event attached to the button)?
You need to understand that MVC doesn't directly reference .aspx pages like WebForms in its URLs. Its main purpose is to separate concerns, that is model (data), controller (logic), and view (presentation).
First, you'd have to create a route matching your URLs, which would now look like this for example : /home/search/This+is+my+search+string
This would call the Search action method of the Home controller, which would get "This is my search string" as an input parameter. This action is responsible for accessing the model and pulling the results probably from a database.
Typically, your search action would then return a ViewResult containing the view placed in the folder /Views/Home/Search.aspx. Here, you can use neither the Postback functionality nor the events of your Web controls like in WebForms, because MVC applications are stateless and not event-driven. It's more like a request/dispatch way of doing things.
Read more about MVC here.
Create a user control called Search.ascx with a form:
<% using (Html.BeginForm ("Search", "Home")) { %>
<input name="search" type="text" size="16" id="search" />
<input type="image" name="search-image" id="search-image" src="search.gif" />
<% } %>
And in your search action all you need is the following:
public class HomeController : Controller
{
public ActionResult Search (string search)
{
throw new Exception (string.Format ("Search: {0}", search));
}
}
In your master page or wherever you can then add
<% Html.RenderPartial ("Search"); %>
You can use a simple javascript in the button's onclick to redirect to the search page:
Search <input type="text" id="go" size="4" /><input type="button" value="<%=Html.Encode(">>") %>" onclick="javascript:window.location='<%=Url.Action("Search", "Home") %>/' + document.getElementById('go').getAttribute('value')" />

Resources