MVC returns page as a file - asp.net-mvc-4

I have an mvc4 project and I am getting a weird result. Whenever I sumit a form and fire up a postback, if the entry is correct it redirects me to the success page which is good. But when my input is invalid and it has to return to the same page, to display the error message, it comes up as a downloadable file. Can anybody please tell me what is going on?
<HttpPost()>
Public Function Collection(oColInfo As CollectionInfoVM) As ActionResult
If ModelState.IsValid Then
oColInfo.CollectionDate = DateTime.Now
m_oAppBase.Collection.AddGroupCollection(oColInfo)
Return View("_Success")
Else
ViewData.Add("PaymentTypes", PaymentType.Dictionary.ToSelectList(oColInfo.PaymentType))
ViewData.Add("PaidBy", PaidBy.Dictionary.ToSelectList(oColInfo.PaidBy.ToString()))
Return View(oColInfo)
End If
End Function
EDIT 1 :
I also found out that my controller is returning my view as JSON. That's why IE is asking me if i wanted to download it. Why is my default return type JSON?
EDIT 2 :
The response type is application/json instead of text/html.
EDIT 3 :
It works when I remove the Html.RenderAction("MainMenu", "Menu") from my layout
Controller action looks like this;
Public Function MainMenu() As PartialViewResult
' Let's see if we have an unprocessed turnin from this district
Dim dtDate As Date = DateTime.Now
Dim colDistStatus As List(Of DistrictStatus) = m_oAppBase.TurnIn.GetNextTurnInStatus()
ViewData.Add("DistrictStatus", colDistStatus)
Return PartialView("_MainMenu")
End Function

Why is my default return type JSON?
ActionResult includes JsonResult too.so when you use ActionResult and you post data from ajax ,your default returns Json.
But when my input is invalid and it has to return to the same page
for validate form in client side,you have to use valid method in your script.it validates form in clientside and doesnt post to your action.
JqueryCode:
if ($('form').valid()) {
$.ajax({});
});

Okay, so looking around I found out that there was a partial view on the page with attribute that returns JSON and when I submit the button this get's fired up too and returned to the browser. I removed the HttpPost attribute and it fixed it. sigh

Related

sitefinity ActionResult missing query string

I have widget and in the ActionResult method it get the query string as parameters. The widget takes the query string and calls a API. Is there anyway I can display a message to the view if its missing the query string?
Code
public ActionResult Index(string UserId, string BlogId)
Yep, do whatever you want
if(String.IsNullOrEmpty(UserId)){
// you get the idea
}
I would do one of the following
Add a property to the model, then handle that state in the view
Load a custom view that's just the message (cleanest)
Check for the empty querystring and do a return this.RedirectPermanent(url); to add the querystring to the page so there's no way it loads without something.

Redirecting to an Action Method from another Action Method in the same controller

I am a Newbie in asp.net and currently I am doing a web page application in MVC4 with Login functionality.
My Index action method looks like this-
public ActionResult Index()
{
var PageModelList1 = new DataAccessLayer.DataAccess().GetPageInfo();
ViewData["MenuList"] = PageModelList1.PageModelList;
return View();
}
and my LogIn action method looks like-
[HttpPost]
public ActionResult LogIn(LogInModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var PageModelList1 = new DataAccessLayer.DataAccess().GetPageInfo(model.UserName,model.Password);
ViewData["MenuList"] = PageModelList1.PageModelList;
return RedirectToAction("Index", "MyController");
}
ModelState.AddModelError("", "login failed");
return PartialView("_LogIn", model);
}
what I need is, when I Login successfully, the RedirectToAction("Index", "Deimos") should take place but the 'MenuList' there should be the new 'MenuList' from LogIn action method. How could I do it?
RedirectToAction will send a 302 response to the browser with the new url as the location header value and browser will make a totally new request to go to that page. This new request has no idea what you did in the previous request. So ViewData will not work. You may consider using TempData.
But TempData's life is only until the next request. After that it is gone. So if you want something on all the subsequent requests(like a menu to be shown to user), I suggest you read it from a database table every time you load the page. You can store the items to a cache after the first read to avoid constant hit(s) to the database if you are worried about that.
Another option is to set the menu items to Session variables and read from there. I am not a big fan of setting stuff like that to session. I prefer to read it from a cache (in which data was loaded from a db call) or so.

Switching MVC view on Post back using strongly typed views/view models

User requests page for Step1, fills out and submits form that contains selected person, so far so good. After validation of ModelState the next viewmodel is constructed properly using the selected person. I then attempt a redirect to action using the newVM but find on entry to Step2 that MVC wipes out the viewmodel attempted to be passed in. I suspect this is due to how MVC attempts to new up and instance based on query string results. I'll put a breakpoint in and check that, but am wondering how does one change a view from a post back with a new view model passed in?
public ActionResult Step1()
{
var vm = new VMStep1();
return View(vm);
}
[HttpPost]
public ActionResult Step1(VMStep1 vm)
{
if (ModelState.IsValid)
{
var newVM = new VMStep2(vm.SelectedPerson);
return RedirectToAction("Step2", newVM);
}
return View(vm);
}
public ActionResult Step2(VMStep2 vm)
{
return View(vm);
}
I can fix this by containing VMStep2 and a partial to Step2 in Step1 view, but that requires hide and seek logic when really I just want user to see Step2.
I don't see why you should want to call RedirectToAction! What it does it the following:
it tells your browser to redirect and like it or not your browser doesn't understand how to handle your object -- what it does understand is JSON. So if you really insist on using return RedirectToAction("Step2", newVM); you should consider a way to serialize your VMStep2 object to JSON and when the browser requests the Redirect, it will be properly passed and created in your action method public ActionResult Step2(VMStep2 vm)
HOWEVER I'd use a much simpler way ---
instead of
return RedirectToAction("Step2", newVM);
I would use
return View("Step2", newVM);
Thanks to everyone for the great input!
Here's what I did...
I created three views MainView, Step1View, Step2View (Step 1 and 2 were partial strong typed views)
I created a MainViewModel that contained VMStep1 and VMStep2
When controller served Step1 the MainViewModel only initialized VMStep1 and set state logic to tell MainView Step1 was to be shown.
When user posted back the MainView containing the MainViewModel, the MainViewModel knew what to do by the answers provided in VMStep1.
VMStep2 was initialized on the post back, and state was set to tell MainView to show Step2. VMStep1 was no longer relevant and was set to null.
User was now able to answer using VMStep2 and all was well.
The key to this working is that some flag tells the view which partial to show, the partial takes a model supporting it's strong type which is initialized at the right time. End result is fast rendering and good state machine progression.

Data is not inserting to the database

I am new to asp .net MVC 4.
I have one text box and the text box value I am fetching from one table.But while clicking on submit button this value I want to insert into different table , which is not inserting and showing error.It is taking value as null.
coding
View
#Html.TextBox("empname", (string)ViewBag.empname, new { #readonly = "readonly" })
controller
[HttpGet]
public ActionResult Facilities()
{
mstEmpDetail emp = new mstEmpDetail();
emp = db.mstEmpDetails.Single(x => x.intEmpId == 10001);
ViewBag.empname = emp.txtEmpFirstName;
return View();
}
[HttpPost]
public ActionResult Facilities(TrnBusinessCardDetail bc)
{
var empname1 = ViewBag.empname;
bc.txtfirstName = empname1;
db.TrnBusinessCardDetails.Add(bc);
db.SaveChanges();
return RedirectToAction("Facilities");
}
While I was working with normal text box it was inserting properly,but when I have retrieve
fro DB then i am getting this problem ?
How to solve this problem ?
Viewbag is a one way street - you can use it to pass information to the view, but you cannot use it to get the information from the view. The statement ViewBag.empname in your POST method has a value of null in your code.
As suggested by #dotnetom, ViewBag is a one way street. MVC is stateless so a POST request is not a "Round Trip" from previous get request. Thus your ViewBag can not hold its state.
MVC can determine (and construct) your action parameters from Form Parameters. In your case you have added a textbox with name "empname". So you should get this value as parameter in your POST request.
[HttpPost]
public ActionResult Facilities(TrnBusinessCardDetail bc, string empname)
{
bc.txtfirstName = empname;
db.TrnBusinessCardDetails.Add(bc);
db.SaveChanges();
return RedirectToAction("Facilities");
}
This would be simplest of solution given your problem. More appropriate would be binding your textbox directly with you model property. This way you will not have to worry about retrieving and assigning property value to model in your controller.
I think the problem is when you are using var empname1 = ViewBag.empname; in post controller because ViewBag.empname lost its value at that time.

Specifyng a default message for Html.ValidationMessageFor in ASP.NET MVC4

I want to display an asterisk (*) next to a text box in my form when initially displayed (GET)
Also I want to use the same view for GET/POST when errors are present) so For the GET request
I pass in an empty model such as
return View(new Person());
Later, when the form is submitted (POST), I use the data annotations, check the model state and
display the errors if any
Html.ValidationMessageFor(v => v.FirstName)
For GET request, the model state is valid and no messages, so no asterisk gets displayed.
I am trying to workaround this by checking the request type and just print asterisk.
#(HttpContext.Current.Request.HttpMethod == "GET"? "*" : Html.ValidationMessageFor(v=> v.FirstName).ToString())
The problem is that Html.ValidationMessageFor(v=> v.FirstName).ToString() is already encoded
and I want to get the raw html from Html.ValidationMessageFor(v=> v.FirstName)
Or may be there is a better way here.
1. How do you display default helpful messages (next to form fields) - such as "Please enter IP address in the nnn.nnn.nnn.nnn format) for GET requests and then display the errors if any for the post?
2. What is the best way from a razor perspective to check an if condition and write a string or the MvcHtmlString
Further to my last comment, here is how I would create that helper to be used:
public static class HtmlValidationExtensions
{
public static MvcHtmlString ValidationMessageForCustom<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string customString)
{
var returnedString = HttpContext.Current.Request.HttpMethod == "GET" ? customString : helper.ValidationMessageFor(expression).ToString();
return MvcHtmlString.Create(returnedString);
}
}
And it would be used like this #Html.ValidationMessageForCustom(v=> v.FirstName, "Please enter IP address in the nnn.nnn.nnn.nnn format")