Getting Media from code in repository - umbraco

I'm working in Umbraco 7 and I'm trying to map data to a custom entity i have created. Mapping strings, int ect. is quite simple but can someone tell me how i can map content created from Media picker, Multi Media picker and Content picker?
My simple model:
public class Frontpage : Master
{
public string Headline { get; set; }
public HtmlString Content { get; set; }
public string Image { get; set; }
public IEnumerable<XXXX> Images { get; set; } <-- What class/type should I place here (IMedia mayby)
public IEnumerable<XXXX> Links { get; set; } <-- What class/type should I place here (IContent mayby)
public IEnumerable<NewsItem> News { get; set; }
}
In my repository I have this method:
public Frontpage GetFrontPage(IPublishedContent content)
{
var imageObject = <-- How do I map a image from image picker here
var imagesObject = <-- How do I map images from multi media picker here
var linksObject = <-- How do I map a multiple links from content picker here
var model = new Frontpage {
Headline = !string.IsNullOrEmpty(content.GetPropertyValue<string>("headline")) ? content.GetPropertyValue<string>("headline") : content.Name,
Content = new HtmlString(content.GetPropertyValue<string>("content")),
Image = <-- And finally what goes here,
Images = <-- And finally what goes here,
Links = <-- And finally what goes here,
News = null
};
return model;
}
I hope this makes sence to some of you guys/girls ;o)

I found that i was able to call TypedMedia and TypedContent in my repository like this:
var helper = new UmbracoHelper(UmbracoContext.Current);
var image = helper.TypedMedia(content.GetPropertyValue("image"));
var link = helper.TypedContent(content.GetPropertyValue("link"));
this way I can get what I want for both media and content picker ;o)

Related

Use UIOMaticField or backoffice controls in Ui-O-Matic Umbraco

I am new to Umbraco CMS. I am using Ui-O-Matic plugin in my project.
Ui-O-Matic allows easy CRUD operation for database. But I want to use backoffice controls like file, textarea, etc.
So I am using UIOMaticFielld like this in database.cs file.
[Column("newsDetail")]
[UIOMaticField("News Detail","Add Details",View ="textarea")]
public string newsDetail { get; set; }
[Column("newsImage")]
[UIOMaticField("Image","Upload Image",View ="file")]
public string newsImage { get; set; }
Problem is when I make any change in database, I have to refresh database.tt file to get database changes. But it recreates database.cs file and my previous changes:
[UIOMaticField("News Detail","Add Details",View ="textarea")]
removes from database.cs file. And every time I have to do the same changes.
Please guide me what should I do to keep my custom changes as it is even I refresh database.tt file?
Other better way to do CRUD operation is also preferable.
After googling a lot, I found that as database.cs file is auto generated, I must not do custom changes in it.
I found another way to use backoffice controls. Let me explain here, may it will help to other.
Instead of writing UIOMatoicField in databse.cs file, create model to do the same.
Make below changes in "Models/Generated/database.tt" file
// Settings
ConnectionStringName = "umbracoDbDSN"; // Uses last connection string in config if not specified
Namespace = "Generator";
RepoName = "";
GeneratePocos = true;
ClassPrefix = "";
ClassSuffix = "";
// Read schema
var tables = LoadTables();
tables["Course"].Ignore = true; // Prevents table to include in databse.cs file
tables["News"].Ignore = true;
if (tables.Count>0)
{
#>
<## include file="UIOMatic.Generator.ttinclude" #>
<# } #>
Then create new Model as below. For ex. "Models\NewsModel.cs"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using UIOMatic.Attributes;
using UIOMatic.Enums;
using UIOMatic.Interfaces;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace EdumentUIOMatic.Models
{
[Umbraco.Core.Persistence.TableName("News")]
[PrimaryKey("newsId")]
[UIOMatic("News", "icon-box-open", "icon-box-open", RenderType = UIOMaticRenderType.List, ConnectionStringName = "umbracoDbDSN")]
public class NewsModel: IUIOMaticModel
{
[UIOMaticIgnoreField]
[Column("newsId")]
public int newsId { get; set; }
[Column("newsTitle")]
[UIOMaticField("News Title", "Add Title")]
public string newsTitle { get; set; }
[Column("newsDetail")]
[UIOMaticField("News Detail", "Add Details", View = "textarea")]
public string newsDetail { get; set; }
[Column("newsImage")]
[UIOMaticField("Image", "Upload Image", View = "file")]
public string newsImage { get; set; }
[Column("isDeleted")]
[UIOMaticField("Hide News", "Check if you want to hide this news")]
public bool isDeleted { get; set; }
[System.Web.Http.AcceptVerbs("GET", "POST")]
public IEnumerable<Exception> Validate()
{
return new List<Exception>();
}
}
}
Now if you will reload database.tt file to get updated database, your code will not be removed.

How to get data from custome-controller,model in umbraco?

Hi i am started working on umbraco CMS can anybody tell me how to display contents from model to controller and return data to respective view, want to do something like this :-
ContactViewModel.cs
public int id { get; set; }
public string Name { get; set; }
public string address { get; set; }
public string Email { get; set; }
public string phone { get; set; }
ContactController.cs
var result = new ContactViewModel()
{
id = 1,
address = "ghivto",
Email = "nimesh#gmail.com",
Name = "Nimesh khatri",
phone = "9898989898"
};
return View("contactsDemo",result);
how do i list above data to particular view..? i had already tried "https://www.youtube.com/watch?v=sDQwu_DzYyc" but still i didn't get...can anyone elaborate it..thanks in advance..
SurfaceController exposes a controller like you would use in standard MVC and also gives access to the Umbraco helpers.
public MyController : SurfaceController {
[ChildActionOnly]
public PartialViewResult MyAction(SomeObject data)
{
var result = new ContactViewModel()
{
id = 1,
address = "ghivto",
Email = "nimesh#gmail.com",
Name = "Nimesh khatri",
phone = "9898989898"
};
return View("~/Views/PartialViews/contactsDemo.cshtml",result);
}
}
You can access this data from a Template's razor view or a Macro partial by using:
#Html.Action("MyAction","MyController", new { data = new { Test = "I am data" } })
Note: The data passing can be anything, from a single string to full object which binds to variables at the action.
As with MVC there a few ways to access a partial view file. The above example has an "absolute" path, which you could also match your view folder structure to the name of the controller and the view name to the action name. (MyAction.cshtml).
If you want to do that in Umbraco, and still have access to the Umbraco tempting system etc, you need to use a SurfaceController. This is a controller that inherits all of the useful Umbraco Stuff.
Basically, you'd create your ViewModel, and then a Surface Controller to handle all the actions (Render, Process etc). You'd then call that Surface Controller on your Umbraco View for the Contact Page (or whichever page you want this to show on).
It looks like the video you linked to already covers how to do this, but you can find an example that's pretty similar to your example here: http://creativewebspecialist.co.uk/2013/07/22/umbraco-mvc-what-on-earth-is-a-surface-controller/

How to make Model to replace CustomMembershipDB

I just followed an MVC tutorial on creating an image Gallery, which connects the Controller to the data connection, like this:
ImageController.cs:
...
private CustomMembershipDB db = new CustomMembershipDB();
public ViewResult Index()
{
return View(db.lm_pics.ToList());
}
...
Instead of connecting directly to CustomMembershipDB, I'd like to use my own Model named GalleryModel.cs. I'm thinking this would allow me to create more functionality that just direct data access.
I am not sure how to write this model, or how to reference it in the controller so that it behaves the same way as a direct database connection does now.
Currently, my GalleryModel.cs file looks lke this (edited to correct error):
namespace LMProj_MVC.Models
{
public class GalleryModel
{
public string Picname { get; set; }
public string Decription{ get; set; }
public int Userid { get; set; }
}
public class PicDBContext : CustomMembershipDB
{
public DbSet<GalleryModel> GalleryModel { get; set; }
}
}
I'd like to be able to show the gallery using an iEnumberable list as I am doing now, in addition to creating other methods. Could someone tell me what I'm missing?
You need to create an instance of your model object for each of your database pictures. You could use LINQ to do this, for example:
var picSummaries = db.lm_pics.Select(pic => new GalleryModel{
Picname = pic.Name,
Description = pic.Description,
Userid = pic.User.Id
});
Or you could use a for each loop:
var picSummaries = new List<GalleryModel>();
foreach (var pic in db.lm_pics)
{
picSummaries.Add(new GalleryModel{
Picname = pic.Name,
Description = pic.Description,
Userid = pic.User.Id
});
}
then return the view as before:
return View(picSummaries);

Create object with list of properties and pass it to Controller

Perhaps there is an easy solution for my problem but I simply cannot seem to find it. I have read lots of tutorials about Knockout so I get the basics but I ask this question because my entity-structure is a bit more complicated than a person with a name and a list of friends which may or may not be on Twitter (Video on Channel9: Helping you build dynamic JavaScript UIs with MVVM and ASP.NET). Here's my situation:
I have a class PersonnelClass with this basic structure:
[Serializable]
//The interface is for the implementation of 'Name' and 'Description'
public class PersonnelClass : IPersonnelClassOrPerson
{
public PersonnelClass() : this(Guid.NewGuid(), "", "") { }
public PersonnelClass(Guid id, String name, String description = null)
{
if (id == Guid.Empty) { throw new ArgumentNullException("id"); }
Id = id;
Name = name;
Description = description;
Properties = new PropertyCollection();
}
public Guid Id { get; private set; }
public String Name { get; set; }
public String Description { get; set; }
public PropertyCollection Properties { get; private set; }
}
The PropertyCollection class and associated AbstractProperty class look like this:
[Serializable]
public class PropertyCollection: List<AbstractProperty> { }
[Serializable]
public abstract class AbstractProperty: IEntity, IProperty
{
public AbstractProperty(String name, String description = null) : this(Guid.NewGuid(), name, description) { }
public AbstractProperty(Guid id, String name, String description = null)
{
if (id == Guid.Empty) { throw new ArgumentNullException("id"); }
if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); }
Id = id;
Name = name;
Description = description;
}
public Guid Id { get; private set; }
public String Name { get; private set; }
public String Description { get; private set; }
}
In my Controller, I create an instance of a PersonnelClassViewModel that has this structure:
public class PersonnelClassViewModel
{
public PersonnelClass PersonnelClass { get; set; }
public List<AbstractProperty> Properties { get; set; }
}
I fill this viewmodel with a new PersonnelClass and two test-properties to pass to my View like this:
var properties = new List<AbstractProperty>
{
new TextProperty("prop1", "descr1"),
new TextProperty("prop2", "descr2")
//TextProperty is derived from AbstractProperty
};
var vm = new PersonnelClassViewModel { Properties = properties };
return View(vm);
I get everything in my View as I wanted. From the View I want to create a new PersonnelClass with a set of selected properties. I have the fields for Name and Description and to add the properties I have a ListBox with the properties that already exist (for demo-purpose they came from the controller now). Through a bit of Knockout JavaScript code I can select items from this list and populate an HTML select-control () with the selected properties to add to the PersonnelClass. This all works fine, until I want to build up an object to pass back to the Controller and create the PersonnelClass.
My question is: what Knockout JS code is needed to build up this object and pass it to the Controller by submitting the form and in my Controller how should I receive this object, meaning: what type of object should this be (PersonnelClass, PersonnelClassViewModel, ...) ?
If any more info/code is needed, please do ask. Thanks in advance!
Update after answer of 'B Z':
I followed a few more of Steven Sanderson's tutorials about this to be sure I understand this, especially the one you provided in your answer. Now I have following code in my View to start with:
var initialData = #Html.Raw(new JavaScriptSerializer().Serialize(Model));
var viewModel = {
personnelClassViewModel : ko.mapping.fromJS(initialData),
properties : personnelClassViewModel.Properties,
selectedProperties : ko.observableArray([]),
addedProperties : ko.observableArray([])
};
ko.applyBindings(viewModel);
The variable 'initialData' contains the values I expect it to have but then I get the following error:
Microsoft JScript runtime error: 'personnelClassViewModel' is undefined
I have no clue anymore. Can anyone help me fix this?
Steven Sanderson has an example of how to to work with variable length lists and knockoutjs
http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/
Having said that, I think your problem isn't so much on the knockout side and more on the how to databind the data correctly on the server side. In the link above, Steven uses a FromJson attribute to model bind which you may find useful...
HTH

ASP.NET MVC 2 View (ViewModel) -> MS Word or PDF Generation?

Id like to have my mvc 2 app generating reports in both MS Word and PDF formats....currently working on Word. I found this:
http://www.revium.com.au/articles/sandbox/aspnet-mvc-convert-view-to-word-document/
Which i think basically streams the view output from a controller action to a word document....
public ActionResult DetailedReport()
{
//[...]
return View();
}
public ActionResult DetailedReportWord()
{
string url = "DetailedReport";
return new WordActionResult(url, "detailed-report.doc");
}
And heres the class that extends ActionResult
public class WordActionResult : ActionResult
{ private string Url { get; set;}
private string FileName { get; set;}
public WordActionResult(string url, string fileName)
{
Url = url;
FileName = fileName;
}
public override void ExecuteResult(ControllerContext context)
{
var curContext = HttpContext.Current;
curContext.Response.Clear();
curContext.Response.AddHeader("content-disposition", "attachment;filename=" + FileName);
curContext.Response.Charset = "";
curContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
curContext.Response.ContentType = "application/ms-word";
var wreq = (HttpWebRequest) WebRequest.Create(Url);
var wres = (HttpWebResponse) wreq.GetResponse();
var s = wres.GetResponseStream();
var sr = new StreamReader(s, Encoding.ASCII);
curContext.Response.Write(sr.ReadToEnd());
curContext.Response.End();
}
}
Which looks pretty good - but my problem is that my view renders from a ViewModel, here is the Action
[HttpPost]
public ActionResult StartSearch(SearchResultsViewModel model)
{
SearchResultsViewModel resultsViewModel = _searchService.Search(model.Search, 1, PAGE_SIZE);
return View("Index", resultsViewModel);
}
and here is my model:
public class SearchResultsViewModel
{
[SearchWordLimit]
public string Search { get; set; }
public IEnumerable<Employee> Employees { get; private set; }
public IEnumerable<Organization> Organizations { get; private set; }
public PageInfo PageInfo { get; private set;}
public SearchResultsViewModel()
{
}
public SearchResultsViewModel(string searchString, IEnumerable<Employee> employees, IEnumerable<Organization> organizations, PageInfo pageInfo)
{
Search = searchString;
Employees = employees;
Organizations = organizations;
PageInfo = pageInfo;
}
}
I'm having trouble kinda connecting the two - to stream the view using my viewmodel to pdf
There's nothing out of the box in ASP.NET MVC that allows you to build a PDF or Word file from a POCO class. You have to build it manually or using a third party library. Once you have done this you could easily write the bytes to the response stream:
public ActionResult SomeAction(SearchResultsViewModel model)
{
byte[] pdf = GeneratePdfForModel(model);
return File(pdf, "application/pdf");
}
The GeneratePdfForModel method will of course be specific on what library/API you are using to generate the document.
The trick is to generate the PDF file from the MS-Word file. You most likely need a 3rd party component for this.
If you don't need perfect conversion fidelity, just something that is 'good enough', then try Aspose.Words. If you need perfect conversion Fidelity then try a product I have worked on, it allows the conversion of all typical MS-Office types to PDF format using a web services interface.
I'm a bit late to this, but from what I can see:
public ActionResult DetailedReportWord()
{
string url = "DetailedReport";
return new WordActionResult(url, "detailed-report.doc");
}
Your url is pointing back to the same Action, it should be pointing at your "StartSearch" action as that is the one that produces the HTML you are wanting to be opened by Word. It needs to be a full URL too I think.
I am trying to use this method too, I found it from your question! I'm having issues passing over the authorised credentials in the WebRequest.Create(Url) for the source View however.

Resources