RedirectToAction usage in asp.net mvc - asp.net

I want to post some questions about ASP.Net MVC. I am not familiar with web developing, But I was assigned to the web part of a project. We are doing the following: first, we create get & set properties for the person data:
public class Person
{
public int personID {get;set;}
public string personName {get;set;}
public string nric {get;set;}
}
and after login, we put the data in a class Person object and we use RedirectToAction like this:
return RedirectToAction("profile","person",new { personID = Person.personID});
It's working normally, but the parameter are shown in the URL. How can I hide them and also
can I hide the action name? Guide me the right way with some examples, please.

The parameter are shown in the URL because that is what the third parameter to RedirectToAction is - the route values.
The default route is {controller}/{action}/{id}
So this code:
return RedirectToAction("profile","person",new { personID = Person.personID});
Will produce the following URL/route:
/Person/Profile/123
If you want a cleaner route, like this (for example):
/people/123
Create a new route:
routes.MapRoute("PersonCleanRoute",
"people/{id}",
new {controller = "Person", action = "Profile"});
And your URL should be clean, like the above.
Alternatively, you may not like to use ID at all, you can use some other unique identifier - like a nickname.
So the URL could be like this:
people/rpm1984
To do that, just change your route:
routes.MapRoute("PersonCleanRoute",
"people/{nickname}",
new {controller = "Person", action = "Profile"});
And your action method:
public ActionResult Profile(string nickname)
{
}
And your RedirectToAction code:
return RedirectToAction("profile","person",new { nickname = Person.nickname});
Is that what your after?

If you don't want the parameter to be shown in the address bar you will need to persist it somewhere on the server between the redirects. A good place to achieve this is TempData. Here's an example:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
And now on the Profile action you are redirecting to fetch it from TempData:
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if (nickname == null)
{
// nickname was not found in TempData.
// this usually means that the user directly
// navigated to /person/profile without passing
// through the other action which would store
// the nickname in TempData
throw new HttpException(404);
}
return View();
}
Under the covers TempData uses Session for storage but it will be automatically evicted after the redirect, so the value could be used only once which is what you need: store, redirect, fetch.

this may be solution of problem when TempData gone after refresh the page :-
when first time you get TempData in action method set it in a ViewData & write check as below:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
now on the Profile action :
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if(nickname !=null)
ViewData["nickname"]=nickname;
if (nickname == null && ViewData["nickname"]==null)
{
throw new HttpException(404);
}
else
{
if(nickname == null)
nickname=ViewData["nickname"];
}
return View();
}

Temp data is capable of handling single subsequent request. Hence, value gone after refresh the page. To mitigate this issue, we can use Session variable also in this case. Try below:
public ActionResult Index(Person _person)
{
Session["personNickName"] = _person.nickName;
return RedirectToAction("profile", "person");
}
And in "profile" actionmethod:
public ActionResult profile()
{
Person nickName=(Person)Session["personNickName"];
if(nickName !=null)
{
//Do the logic with the nickName
}
}

Related

Getting the Object reference not set to an instance of an object exception in ASP.NET Core MVC

I'm trying to connect an object from one View to another. I have a user action history where I have all of my CRUD operations listed. I'm trying to add an action link that when I go to my action history the name of the object that was created/updated/deleted(soft delete), becomes a link that will redirect me to the Edit view of that object. I tried via. #Html.ActionLink like this:
#Html.ActionLink(item.PreduzvePibfkNavigation.NazivPreduzeca, "IzmenaPreduzeca","Preduzece", new {Id = item.PreduzvePibfk}, null)
This is my controller for the 'IzmenaPreduzeca' action:
[HttpGet]
public IActionResult IzmenaPreduzeca(int id)
{
Preduzece preduzece = _preduzece.getById(id);
ViewBag.izabrani = preduzece.NazivPreduzeca;
return View(preduzece);
}
[HttpPost]
public IActionResult IzmenaPreduzeca(Preduzece preduzece, IstorijaPromena istorijaPromena, string razlog)
{
try
{
_preduzece.Update(preduzece);
_preduzece.IstorijaPromene(preduzece, istorijaPromena, CrudType.Update, DateTime.Now, "Branislav Zivanovic", razlog);
_preduzece.SaveToDb();
return RedirectToAction("PregledPreduzeca");
}
catch (Exception ex)
{
return NotFound($"Error, details: {ex.Message}");
}
}
I don't understand why do I get this error
Object reference not set to an instance of an object
Is there another way?
This is the user action history:
Image of the user action history
input parameter id is always 0, fix the action header
[HttpGet("{id}")]
public IActionResult IzmenaPreduzeca(int id)

ASP.NET: Access temp data in ViewBag

I am beginner in ASP.NET and trying to get data in ViewBagby using temp data in controller. I got it in user.Username and user.Email but not getting in ViewBag.Name and ViewBag.Email respectively. My code is given below please guide me how can i get it in ViewBag?
QuestionsContoller.cs
public class temp {
public string username { get; set; }
public string email { get; set; }
}
public ActionResult Question() {
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Question(User user) {
temp temp_user = new temp();
temp_user.email = user.Email;
temp_user.username = user.Username;
return RedirectToAction("Answers" , temp_user);
}
public ActionResult Answers(temp temp_user) {
User user = new Models.User();
user.Username = temp_user.username;
user.Email = temp_user.email;
ViewBag.Name = user.Username;
ViewBag.Email = user.Email;
return View(user);
}
You cannot redirect with a payload. A redirect is an empty-bodied response with typically a 302 status code and a Location header indicating the URL that should be requested next. The client, upon receiving this type of response, will generally then go ahead and make a new request for that URL. Importantly, the client will not know or care to pass any additional data along with this request, so you cannot enforce that something like your temp object is included.
If you need to persist that data between requests, you can add it to TempData:
TempData["temp_user"] = temp_user;
And then fetch it in the action you redirect to via:
var temp_user = TempData["temp_user"] as temp;
Alternatively (and preferably), you'd simply redirect with the user id in tow, and then simply look up the user again. The use of sessions (which TempData is) should be avoided as much as possible.
return RedirectToAction("Answers", new { userId = user.Id });

How to handle a POST request to a URL that contains route parameters?

I'm working on an ASP.NET MVC4 web app, and I have a controller method for handling a GET request with an id in the URL, like so ...
[PortalAuthorization]
public ActionResult View(int id)
{
// get the individual ftp log
PortalFTPLog log = PortalFTPLogs.Get(id);
if (log == null)
{
TempData["Error"] = "The provided ftp log id does not exist.";
return RedirectToAction("Index");
}
// get the available matters to tie uploads to
ViewBag.matters = PortalMatters.Get();
return View(log);
}
In my view for this controller method, I have a form so that they can update it, that I want to POST back to the same URL. A URL like foo.com\items\1. Thats what the function above handles.
How do I make a function that handles a POST request for a function that requires a parameter, though? IN previous POST handlers I create a FormsCollection param, but when I add it to the param list for this function, the id param is null.
[HttpPost]
[PortalAuthorization]
public ActionResult View(FormCollection collection, int id)
{
PortalFTPLog log = PortalFTPLogs.Get(id);
if (log == null)
{
TempData["Error"] = "The provided ftp log id does not exist.";
return RedirectToAction("Index");
}
// update the matter id and save to database
log.Matter = Convert.ToInt32(collection.Get("matter"));
log.Save();
TempData["Notice"] = "The FTP log meta data has been updated.";
return RedirectToAction("View", new { id = id });
}
You need to provide RouteValues in Html.BeginForm on your View:
#using (Html.BeginForm(new {id = someIntIdValue}))
{
// Your form code
}

MVC4 - ContextDependentView - What does it mean?

I have just started using MVC4 and the first action method that I look at has something new. I checked out the internet and can't find anything about this:
public ActionResult LogOn()
{
return ContextDependentView();
}
Does anyone know what a ContextDependentView is ?
Something new to me.
It's purpose is to facilitate View or PartialView action results for the Login and Register actions.
private ActionResult ContextDependentView()
{
string actionName = ControllerContext.RouteData.GetRequiredString("action");
if (Request.QueryString["content"] != null)
{
ViewBag.FormAction = "Json" + actionName;
return PartialView();
}
else
{
ViewBag.FormAction = actionName;
return View();
}
}
Like other things in MVC it is done by convention... the convention here is when the Request.QueryString contains a ?content=xxxx, it prepends "Json" to the action name, stuffs it a ViewBag property and returns the partial version of the View. For example:
A request for /Account/Login?content=test would be resolved to ViewBag.FormAction = "JsonLogin"; and then return a partial.
A request for /Account/Login has no content query string so its form action remains ViewBag.FormAction = "Login";

ASP.NET MVC SEO URL

My goal is to have the url routing as following:
http://www.abc.com/this-is-peter-page
http://www.abc.com/this-is-john-page
What is the simplest way to achieve this without placing controller name an function name in the url above? If page above not found, I should redirect to 404 page.
Addon 1: this-is-peter-page and this-is-john-page is not static content, but is from database.
Similar to KingNestor's implementation, you can also do the followings which will ease your work:
1) Write Your Model
public class MyUser{public String UserName{get; set;}}
2) add route to global asax
routes.MapRoute(
"NameRouting",
"{name}",
new { controller = "PersonalPage", action = "Index", username="name" });
3) Roll your own custom model binder derived from IModelBinder
public class CustomBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var username = getUserNameFromDashedString(request["username"]);
MyUser user = new MyUser(username);
return user;
}
}
4) in your action:
public ActionResult Index([ModelBinder(typeof(CustomBinder))] MyUser usr)
{
ViewData["Welcome"] = "Viewing " + usr.Username;
return View();
}
I personally wouldn't suggest a route like that but if it meets your needs you need to do something like:
Have the following route in your Global.asax file:
routes.MapRoute(
"NameRouting",
"{name}",
new { controller = "PersonalPage", action = "routeByName" });
Then, in your "PersonalPageController", have the following method:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult routeByName(string name)
{
switch (name)
{
case "this-is-peter-page": return View("PeterView");
case "this-is-john-page": return View("JohnView");
case Default: return View("NotFound");
}
}
Make sure you have the appropriate views: "PeterView", "JohnView" and "NotFound" in your Views/PersonalPage/.
I don't think this can be done. AFAIK ASP.NET MVC recognizes routing parameters via the character "/".
Your format, on the other hand, goes by "{controller}-is-{id}-{action}" -- so there is no way the controller can be distinguished from the id and the action.
I think using "/" characters doesn't affect or degrade SEO; it only affects human readability and retention of the URL.
Anyway, the following URL is possible: http://www.abc.com/this-is-the-page-of/Peter by adding another route in the Global.asax RegisterRoutes method:
routes.MapRoute(
"AnotherRoute",
"this-is-the-page-of/{id}",
new { controller = "PersonalPage", action = "Details", id = "" }
);
...assuming that PersonalPageController implements a Details ActionResult method that points to the desired page.

Resources