render a string in MVC just like rendering a view, possible? - asp.net

is it possible to render a string like this:
public ActionResult Do(){
s = " hello, click here <%=Html.ActionLink(\"index\",\"index\") %> ";
return Content(RenderString(s));
}
the result would something like this:
hello, click here index

What is the purpose of this? You have a controller action which tries to evaluate some string WebForms syntax string and return it as content. Why not simply return the view and have this view do the job?
If you want dynamic to have views (coming from a database or something) you could write a custom view engine and personalize their location so that your action looks like this:
public ActionResult Do()
{
return View();
}
and the corresponding view contents will be fetched from your custom view engine instead of the standard file locations.
If you want to render the contents of a view into a string this has been covered in many blog posts. Finally if you are dealing with sending views as emails there are probably better solutions.
So depending on what you are trying to achieve there might be different solutions.

public String Do(){
string s = " hello, click <a href='" + Url.Action("Index") +"' > here </a>";
return s;
}
then if you call {Controller}/Do you will have your string
EDITED
Marco

Related

Is using Viewbag for remembering past form inputs a bad idea?

I have a small asp.net core mvc application that basically consists of a form that a user can input some constraints into, and then get a filtered list of data depending on those constraints.
The controller action for filtering data basically looks like this:
[HttpPost]
public async Task<IActionResult> Query(QueryModel query)
{
var customers = await _context.Customers.AsQueryable().FilterCustomerList(query);
return View("Index", customers);
}
Now, my issue is that I would like the inputs in the fields to persist after entering them and being redirected to the view again. Right now they are currently just reset.
One way of doing this that I found was using viewBag. An example for a single query attribute is this:
public async Task<IActionResult> Query(QueryModel query)
{
var customers = await _context.Customers.AsQueryable().FilterCustomerList(query);
ViewBag.Name = query.Name;
return View("Index", customers);
}
and then the inpuit html elelment would look like:
<div class="col-md-4">
<input name="Name" type="text" placeholder="First name" value="#ViewBag.Name"class="form-control">
</div>
And this makes sure that if something has been entered into a field, it will now be entered into the field when after the query has been submitted.
But when I read up on ViewBag, I understand that a lot of .net developers have an aversion to it. It's not safe, the compiler can't catch errors in it easily etc.
Also, If I were to add all the input fields in my form to the viewbag, I would need a lot of lines of ViewBag.Attribute = query.SomeAttribute (20-30). Which seems like a code-smell too.
Is there any nicer way to do what I am trying to here?
You haven't included your QueryModel class and that class could be a key point to a cleaner approach.
You see, usually the user data, POSTed to your action is bound to the model, from there it's rendered on the form and is POSTed again. The model binding is where an input of a specific name is bound to a model member of the same name.
Thus, there's no need for viewbags.
More formally:
The Model
public class QueryModel
{
[your-validators-in-attributes, e.g. Required or MaxLength
there can be multiple validators]
public string Name { get; set; }
}
The controller:
[HttpPost]
async Task<IActionResult> Query(QueryModel query)
{
// query.Name is there, bound from the view
}
The View:
#model .....QueryModel
<div>
#Html.TextBoxFor( m => m.Name, new { placeholder = "a placeholder" } )
</div>
The html helper does two things
renders an input of the given name (Name in this case)
sets its value depending on the actual value from the model
In newer ASP.NETs you can achieve similar result by using tag helpers, where instead of Html.TextBoxFor(...) you write
<input asp-for="Name" />
These two approaches, using html helpers or using tag helpers are equivalent. In both cases there's no need for view bags.

How to make a search for item and show the result in seperated page [ASP MVC]

I just want to make a search for my site , and before I start work on that I just want to sort my work steps .
My site type is books site . and here is what I want to know :
I have a search box in my navbar .
when someone entered a book name to search I want to show the result of this
search in this page :
Localhost/Search?string=C++
How I can call the method that will process the search from the view
?
How should the controller method looks like , also the view page.
How to make a paging to the search page ?
I don't need a code , I just want from someone to help me with a list of steps I should do , to make the search as I requested and thanks a lot guys ....
You can keep your input box for search inside a form and keep the form's method value to be GET.
#using (Html.BeginForm("Search", "Students", FormMethod.Get, null))
{
<input type="text" name="searchTerm" />
<input type="submit" />
}
Now you should have an action method called Search inside your StudentsController which accepts a string value in a parameter named searchTerm.
public ActionResult Search(string searchTerm)
{
// use searchTerm variable to get data and pass to view
return View();
}
Now in your view (~/Views/Students/Search.cshtml), you can use the passed data to display the search results.
For paging, you may add another parameter to your action method which you will use to get a specific sub set of the data.
public ActionResult Search(string searchTerm,int page=1,size=10)
{
// use searchTerm variable to get data and pass to view
// page number is in page variable
// size is in size variable
return View();
}
Now you need to adjust your view to show all the page numbers and link to the same action method and pass the page number in url like
/Students/Search?searchTerm=Java&page=2&size=25

ASP.NET Razor - Can I put a link in a ternary operator?

I have a ternary operator in my MVC4 View:
#(modelrecord.Website == null ? "" : modelrecord.Website.Replace("http://","") )
This works, but I want to make the website record a hyperlink. Is this possible?
Note: I'm replacing the "http://" prefix because it's ugly.
If I put in the actual string with Html.Raw, the angle brackets are escaped, and I still don't get a link.
You should probably be using DataAnnotations and the #Html.DispayFor helper.
public class ModelRecord
{
[DataType(DataType.EmailAddress)]
public String EmailAddress { get; set; }
[DataType(DataType.Url)]
public String Website { get; set; }
}
Then:
email me at #Html.DisplayFor(x => x.EmailAddress)
or visit me online at #Html.DisplayFor(x => x.Website)
The DataTypeAttribute handles things like urls, emails, etc. and formats them depending.
If you want to customize all Urls, you can create a display template for it:
~/Views/Shared/DisplayTemplates/Url.cshtml
#model String
#if (!String.IsNullOrEmpty(Model))
{
#Model.Replace("http://", "")
}
else
{
#:Default text when url is empty.
}
DisplayTemplates (like EditorTemplates) is a convention-based path that MVC uses. because of this, you can place the template in the Shared directory to apply this change site-wide, or you can place the folder within one of the controller folders to only have it apply to that controller (e.g. ~/Views/Home/Displaytemplates/Url.cshtml). Also, Url is one of the pre-defined templates included for use with DisplayType, along with the following:
Url
EmailAddress
HiddenInput
Html
Text

ASP.NET MVC 2 - Simple Search Page

I just started ASP.NET MVC (coming from WebForms) and I'm struggling with some really basic concepts.
I want to create a single page that uses a textbox for date input. I would like the date input to be passed to the index of my controller which looks like this:
public ActionResult Index(int month,
int day,
int year){
var visitors = visitorRepoistory.FindVisitorsByDate(month, day, year).ToList();
return View("Index", visitors);
}
Up to this point I have used scaffolding with strongly typed views so everything was kind of glued together for me.
What would/should my view look like? Would I use an actionlink (this is a get request after all, right?) and not a submit button.
Thanks.
I thought about this for a while before trying to come up with an answer. What threw me initially was the concept of turning a single text input string into it's month, day, and year components. In ASP.NET MVC, it would be much easier to just accept the string for the date. This way, your code changes to:
public ActionResult Index(string date) {
try
{
DateTime dtDate = DateTime.Parse(date);
var visitors = visitorRepoistory.FindVisitorsByDate(dtDate.month,
dtDate.day, dtDate.year).ToList();
return View("Index", visitors);
}
catch (FormatException)
{
//String was not a valid date/time
}
}
Are there ways to split it up into 3 ints? I'm sure. But to me, this would be the easiest/quickest way to the goal.
So in the view, you'll have your form looking something like this:
<% using(Html.BeginForm("VisitorSearchController", "Index")) { %>
Enter a date: <%= Html.TextBox("date") %>
<input type='submit' value='Search' />
<% } %>
Where "VisitorSearchController" is the name of the controller you want to post back to. Of course, "Index" is the method you're posting to. I'd stick with the submit button for now unless you're trying to get a LinkButton equivalent on the page. But you can save the "prettying up" part after functionality, right?
Edit: Added view code to the answer.
EDIT after comment:
Simplest way is to make the search input page post (not get) back to some other method, parse the date out, then redirect to the Action you have specified.
If you want to do it through get, then you can use some Javascript trickeration to link to whatever they type in, but I recommend the former.

Problem with displaying image from DB using asp.net MVC 2

I'm having trouble with displaying image from db. I think that method for saving image is working, because I see in DB that varbinary fields have some value, and that image type is correct. Also the size of image. But when I want to display image for product i don't get anything. Just blank space.. here is my code...
public byte[] GetImage(int productID)
{
Product product = products.GetByID(productID);
byte[] imageData = product.ImageData.ToArray();
return imageData;
}
That code is in my controller. Second is code from view :
<% if (product.ImageData != null) { %>
<img src='/product/getimage/<%= Html.Encode(product.ID) %>' alt=""/>
<% } %>
I tried some solutions found here on stack overflow, and everyone do it like this, but it's working for them. I dont have any idea why images aren't displayed. When i look at source code of page at debugging i have :
<img src='/product/getimage/18' alt=""/>
I'm using .net 4.0, MVC 2, VS 2010... Thanks in advance
My guess is that you have a routing issue. If the url /product/getimage/18 should work for your action you need to have a route that looks something like this:
routes.MapRoute("ProductImage",
"product/getimage/{productID}",
new { controller = "Product", action = "GetImage", productID = "" }
);
To confirm this you should use firebug and check the "net" tab (or set a breakpoint in your action and see if it gets hit when you load the page).
I would also recommend using the build in helpers to generate your urls (then this kind of problem will never happen). Instead of src='/product/getimage/<%= Html.Encode(product.ID) %>' you can write src='<%=Url.Action("GetImage", "Product", new { productID = product.ID })%>'
I'm not much of an expert on MVC yet - but from what I can see, I think your GetImage function needs to be an Action Method inside your controller, so it'll need to return an ActionResult?
You'll probably need to set the Content-Type header in the response, too.
This guy looks like he knows what he's talking about...
http://blogs.msdn.com/miah/archive/2008/11/13/extending-mvc-returning-an-image-from-a-controller-action.aspx
Try to change you method to:
public void GetImage(int productID)
{
Product product = products.GetByID(productID);
Response.ContentType = "image/jpeg";
Response.BinaryWrite(product.ImageData.ToArray());
}
You have:
<img src='/product/getimage/18' alt=""/>
Normally i'd say an image tag looks like this:
<img src='/product/getimage/18.jpg' alt=""/>
I needed to register routes in my global.cs file like Mathias suggested.
Also i needed to modify action in my controller to this :
public FileContentResult GetImage(int productID)
{
Product product = products.GetByID(productID);
return File(product.ImageData.ToArray(), product.ImageMimeType);
}
I wish thank you all for your fast answers...

Resources