access child action parameter in its view - asp.net-mvc-4

public class AController : Controller
{
public ActionResult Index()
{
return View();
}
}
and Index view goes like
...
#Html.Action("Index", "BController", new { HasEditPermission = true })
...
BControler goes like
public class BController : Controller
{
public ActionResult Index()
{
return PartialView();
}
}
and this Index Partial view goes like
...
#if (!string.IsNullOrEmpty(Request.Params["HasEditPermission"]) && bool.Parse(Request.Params["HasEditPermission"]))
{
// some html rendering
}
...
here when I do Request.Params["HasEditPermission"] in the partial view, I get null.. but if I include HasEditPermission as a parameter to my Index action of BController then I get the value..
I think, I am not getting it from Request.Params because actual request is to AController Index action which doesn't include this parameter.
But I am wondering how is it binding the value to HasEditPermission parameter of Index action(suppose if I have it there) of BController?
Please could someone tell me how do I access it directly in the view? (I am aware using ViewBag in Index is an option)

You can use ValueProvider.GetValue("HasEditPermission").RawValue to access the value.
Controller:
public class BController : Controller
{
public ActionResult Index()
{
ViewBag.HasEditPermission = Boolean.Parse(
ValueProvider.GetValue("HasEditPermission").RawValue.ToString());
return PartialView();
}
}
View:
...
#if (ViewBag.HasEditPermission)
{
// some html rendering
}
...
Update:
Request.Params gets a combined collection of QueryString, Form, Cookies, and ServerVariables items not RouteValues.
In
#Html.Action("Index", "BController", new { HasEditPermission = true })
HasEditPermission is a RouteValue.
you can also try something like this
ViewContext.RouteData.Values["HasEditPermission"]
in your View and subsequent child action views as well..

Related

Redirecting to a response view with a model does not keep model properties

I have a form view that submits form data to the post action on a controler and then redirects to another view that uses logic to display either a success or failure, but the new view just shows blank values for model properties. Here is the post action:
[HttpPost]
public ActionResult ContactUs(TTT.Models.ContactUsModel model)
{
logger.Info(model.URL + "Contact Us Form submitted");
var userkey = model.ValidationKey;
var sessionkey = Session["ContactUsKey"];
var lastsubmission = Session["ContactUsTime"];
model.Response = "success";
//first check if honeypot was populated via a bot and if so send it to the success page without doing anything
if (model.WorkAddress != "")
{
logger.Info("honeypot triggered");
return View("ContactUsResponse", model);
}
I'll leave out the remainder of the controler, but
And here is the view it's redirecting to:
#using TTT.Models
#using Sitecore.Mvc
#model ContactUsModel
<h1>#Model.Title</h1>
<div>#Model.Body</div>
<div>
#if (#Model.Response == "fail")
{
#Model.Failure;
} else
{
#Model.Success;
}
</div>
Instead of returning a new view, call RedirectToAction and return new view from that controller.
[HttpPost]
public ActionResult ContactUs(TTT.Models.ContactUsModel model)
{
//--- Code omitted for brevity
if (model.WorkAddress != "")
{
logger.Info("honeypot triggered");
return RedirectToAction("ContactUsResponse", new { response = model });
}
}
public ActionResult ContactUsResponse(TTT.Models.ContactUsModel response)
{
return View(model)
}

Usage of UseStatusCodePagesWithReExecute with a message not working as expected

I'm using UseStatusCodePagesWithReExecute in my .NET Core 2.1 web app as follows
app.UseStatusCodePagesWithReExecute("/Error/{0}");
and in my Controller I point to 1 of 2 views, a 404.cshtml view and a generic error.cshtml view
public class ErrorController : Controller
{
[HttpGet("[controller]/{statusCode:int}")]
public IActionResult Error(int? statusCode = null)
{
if (statusCode.HasValue)
{
if (statusCode == (int)HttpStatusCode.NotFound)
{
return View(statusCode.ToString());
}
}
return View();
}
}
Now in my page controller I can do the following and it works as expected. It will show error.cshtml
public IActionResult SomePage()
{
return BadRequest();
}
Now if I change the above to the following, my ErrorController does get hit but by the time it does a blank view showing just "Some details" has been loaded in the browser.
public IActionResult SomePage()
{
return BadRequest("Some details");
}
Any ideas why? I want it to load error.cshtml
As #Kirk Larkin said , UseStatusCodePagesWithReExecute middleware won't work and it will only handle the status code .
You can use Result filters to write your custom logic to filter that and return a ViewResult :
public class StatusCodeResultFilter : IAsyncResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
// retrieve a typed controller, so we can reuse its data
if (context.Controller is Controller controller)
{
// intercept the NotFoundObjectResult
if (context.Result is BadRequestObjectResult badRequestObject)
{
// set the model, or other view data
controller.ViewData.Model = badRequestObject.Value;
// replace the result by a view result
context.Result = new ViewResult()
{
StatusCode = 400,
ViewName = "Views/Error/status400.cshtml",
ViewData = controller.ViewData,
TempData = controller.TempData,
};
}
}
await next();
}
}
Register the filter :
services.AddMvc(config =>
{
config.Filters.Add(new StatusCodeResultFilter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
In your view , you can directly get the detail message by :
#Model
Reference : https://stackoverflow.com/a/51800917/5751404

Return a partial view from a razor page Handler

I am having a problem returning a partial view from a razor page, my scenario is
I have a partial view which is a form and that has a model. I have 3 forms residing on a single razor pages
Form A post a ModelA
Form B post ModelB
My problem is, i want to handle thier specific post event on the parent Page which is a razor page.
How would i return this partial view
OnPostModelA(ModelA model)
{
if(! ModelState.IsValid)
return Partialview("_CreateModelA", model);
}
Is this possible using razor pages or this is not possible?
I just want to return the partialview with its designated model using ajax.
As you know ,Razor Pages have no equivalent PartialView method on the PageModel. If you do want to invoke different parial views in PageModel method , simply add a PartialView Helper Method in you PageModel:
[NonAction]
public virtual PartialViewResult PartialView(string viewName, object model)
{
ViewData.Model = model;
return new PartialViewResult()
{
ViewName = viewName,
ViewData = ViewData,
TempData = TempData
};
}
Here I use a ViewData.Model to store your model object , let's say your Model type is named as X1Model :
you can use it across the partial views .
Create a simple partial view named as _CreateModelA.cshtml :
#model HelloModel
AAAAA
<div>
#Model.Model.Welcome
</div>
and another partial view named as _CreateModelB.cshtml :
#model HelloModel
BBBBBBBB
<div>
#Model.Model.Welcome
</div>
At last , you can return PartialView in your PageModel:
public class HelloModel : PageModel
{
public X1Model Model { get; set; }
public ActionResult OnGet(int rand = 0)
{
var flag = rand % 2 == 0 ? true : false;
var model = new HelloModel() {
Model = new X1Model {
Welcome = "Hello,world",
}
};
if (flag)
{
return PartialView("_CreateModelA", model);
}
else
{
return PartialView("_CreateModelB", model);
}
}
[NonAction]
public virtual PartialViewResult PartialView(string viewName, object model)
{
// ...
}
}
Here's a screenshot :
However , it is not recommended to put partial view logic in PageModel . Using it in the Page file as below is much nicer:
#if(){
<partial name="" />
}else{
<partial name="" />
}
In asp dotnet core 2.2, Microsoft added a Partial method to the PageModel class that works similar to the PartialView method on the Controller class. It however doesn't allow you to pass ViewData to the view. So, if you need to do that, then you can create your own PartialViewResult like so:
var resultViewData = new ViewDataDictionary<YourModelType>(ViewData, model);
resultViewData[YourViewDataProperty] = yourViewDataValue;
return new PartialViewResult
{
ViewName = "_Branch",
ViewData = resultViewData,
TempData = TempData
};

how to handle ActionResult in custome class?

i have a class (in project by mvc4 razor on .net 4.5) and want to handle a Redirecting method on it and do not want inherit from controller class.
how can i handle this?it returns ActionResult to redirecting user in some cases like log outing
my main class:
public class SecuritySrv
{
public ActionResult Redirect()
{
return RedirectToAction("Logout", "Account", new { area = "" });
}
}
and i want to use it in some controllers like below:
public ActionResult AccountHome()
{
SecuritySrv SecurityService =new SecuritySrv()
if(.....)
return SecurityService.Redirect();
return view();
}
You can use this code anywhere, and you don't need an UrlHelper or access to the context, so you don't need to inherit the Controller class.
RouteValueDictionary rvd = new RouteValueDictionary
{
{"controller", "Profile"},
{"action", "Users"},
{"area", ""}
};
return new RedirectToRouteResult(rvd);
The RedirectToAction method of controller is just a helper for creating RedirectToRouteResult, you can create it by yourself in your class:
public class SecuritySrv
{
public ActionResult Redirect()
{
RouteValueDictionary routeValues = new RouteValueDictionary();
routeValues["action"] = "Logout";
routeValues["controller"] = "Account";
routeValues["area"] = "";
return new RedirectToRouteResult(routeValues);
}
}
And call this method from your controller in the way you wanted to.

How to detect in a [HttpPost] handler method the view you came from?

Considering this example:
public ViewResult View1()
{
return View();
}
public ViewResult View2()
{
return View();
}
[HttpPost]
public ActionResult Processor(SomeModel model)
{
if (comeFromView1)
{
}
//implementation
return RedirectToAction("View3");
}
Both View1 and View2 have inside a form that post to Processor.
How to detect inside it where did i come from?
One option would be to check Request.UrlReferrer. However, a user can easily spoof the referrer.
A better way would be an action filter which sets the previous action. Like this:
public class SavePreviousActionAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Session["PreviousAction"] = filterContext.RouteData["action"]
}
}
Add this to all actions by registering it as a global filter (in Global.asax):
GlobalFilters.Filters.Add(new SavePreviousActionAttribute());
And then access it in your action:
if (Session["PreviousAction"].ToString() == "View1")
{
// Came from view1
}